1. 程式人生 > >神經網路詳解及技巧

神經網路詳解及技巧

[TOC](神經網路) # 前言 筆者一直在ipad上做手寫筆記,最近突然想把筆記搬到部落格上來,也就有了下面這些。因為本是給自己看的筆記,所以內容很簡陋,只是提了一些要點。隨緣更新。 # 正文 ## step1 建立一個神經網路模型 ###### 一個常見的神經網路——完全連線前饋神經網路 - 全連線:layer和layer之間兩兩連線 - 前饋傳遞方向由後向前,任意兩層之間沒有反饋 - 深度:許多隱含層 $\sigma(\begin{bmatrix}1&-2 \\-1&1\end{bmatrix}\begin{bmatrix}1 \\-1\end{bmatrix}+\begin{bmatrix}1 \\0\end{bmatrix})=\begin{bmatrix}0.98 \\0.12\end{bmatrix}$ 如此一層一層傳遞下去。 最普通的啟用函式$\sigma(z)$為sigmoid函式 $$f(z)=\frac{1}{1+e^{-z}}$$ 其影象為: 當然,現在已經很少使用sigmoid函式做啟用函數了。 #### 本質 通過隱含層來代替原來的特徵工程,這樣最後一個隱含層輸出的就是一組新的特徵,然後通過一個多分類器(可以是$solfmax$函式)得到最後的輸出$y$。 ###### 舉例:手寫識別
## step2 模型評估 對於神經網路,我們採用交叉熵來對 $y$ 和 $\hat y$ 的損失進行計算。(後期我將在生成模型和判別模型中對他進行詳細的描述) ## step3 最佳模型——梯度下降 $backpropation$(反向傳播,也就是所謂的$BP$)在神經網路中是一種有效的方式計算$\frac{\partial{L}}{\partial w}$的方式,我們可以利用很多框架進行計算,如:TensorFlow,Pytorch。 ## 反向傳播($BP$) $L(\theta)$是總體損失函式,$l^n(\theta)$是單個樣本產生的誤差。 計算$L(\theta)= \sum_{n=0}^{N}l^n(\theta)$,只需要計算$\frac{\partial L(\theta)}{\partial w}=\sum_{n=1}^{N}\frac{\partial L(\theta)}{\partial w}$。 ##### 我們取出一個神經元進行分析
易得: $$\frac{\partial l}{\partial w}=\frac{\partial z}{\partial w}\frac{\partial l}{\partial z}$$ ##### Forward Pass $\frac{\partial z}{\partial w}$: 這裡我可以很輕鬆看出$\frac{\partial z}{\partial w}$為上一隱含層輸出的值。 ##### Backward Pass $\frac{\partial l}{\partial z}$: $$\frac{\partial l}{\partial z}=\frac{\partial a}{\partial z}\frac{\partial l}{\partial a} = \frac{\partial a}{\partial z}[\frac{\partial z'}{\partial a}\frac{\partial l}{\partial z}+\frac{\partial z''}{\partial a}\frac{\partial l}{\partial z''}] = \sigma'(z)[w_3 \frac{\partial l}{\partial z'} + w_4 \frac{\partial l}{\partial z''}]$$ 這時候我們會覺得每計算一次梯度相當麻煩,每個引數的梯度都需要層層往後計算,計算量大到無法想象。實際上進行Backward Pass和向前傳播的計算量差不多,我們只需將我們的思維逆轉一下,從最後一層往前計算,也能計算出所有引數的梯度,這時的計算量是線性的,這就是 $BP$ 的思想(個人為很類似於演算法中的動態規劃)。
## 利用keras建立神經網路 建立神經網路的過程,別人以為你在搞什麼特別深奧高大上的東西,其實你只是在搭積木一樣一層一層疊隱含層而已=。= ```python import keras from keras.models import Sequential from keras.layers import Dense model = Sequential() # 建立一個模型 # 搭建網路 '''@param Dense: Fully connect layer input_dim: 輸入層 units: 神經元 activation: 啟用函式 ''' model.add(Dense(input_dim=10, units=500, activation='sigmoid')) # 建立一個神經網路 # 再加一個隱含層 model.add(Dense(units=500, activation='sigmoid')) # 輸出層 model.add(Dense(units=10, activation='softmax')) # 輸出向量長度為10,啟用函式為softmax # loss function model.compile(loss='categotial_crossentropy', # 損失函式:交叉熵 optimizer='adam', # 優化器(都是梯度下降) metrics=['accuracy'] # 指標 ) # batch_size: 將訓練集隨機分為分為幾個batch,每次計算隨機的一個 # 所有batch都計算一次,一個epoch結束 model.fit(x_train, y_train, batch_size=100, epochs=20) # case1: 測試集正確率 score = model.evaluate(x_test, y_test) print('Total loss on Test Set:', score[0]) print('Accuracy of Testing Set:', score[1]) # case 2:模型預測 result = model.predict(x_test) ``` ## 深度學習的技巧 ### 在test上如何改進: #### 新的啟用函式 ###### sigmoid缺點——梯度消失: 有時神經網路層數越深,結果越差,原因可能是梯度消失,比較靠近input的幾層梯度很小,靠近output的幾層梯度較大,在前幾層還未怎麼更新引數時,後幾層已經收斂。因為每經過一個sigmoid,$\Delta w$的影響就會被消弱。 ###### ReLU: - 當 input > 0 時,output = input - 當 input < 0 時,output = 0 在input < 0 時,相當於該節點被移除,整個網路就是 a thinner linear network,如果時線性的話,梯度不會遞減。 你可能會說這個線性模型如何處理那些複雜的非線性模型,畢竟不是所有問題都和線性一樣美好,你要注意了我們這是deep learning,關鍵在於這個“deep”,這是一個有著數層幾千個神經元的網路,它們疊加的效果就是一個非線性的模型,是一個很複雜的function。對於ReLU activation function的神經網路,只是在小範圍內是線性的,在總體上還是非線性的。 好處: 1. 比sigmoid處理起來快 2. 無窮多的sigmoid疊加起來的結果(不同的bias) 3. 可以處理梯度消失 變種: - Leaky ReLU - Parametric ReLU ###### Maxout —— 讓network自動學習的啟用函式 方法: 1. 先將輸入分組,如2個一組或3個一組 2. 再從每一組中選擇最大的一個 下圖為一個簡單的示例 原理: 其實上面介紹的ReLU為一個特殊的Maxout,理論上Maxout可以擬合任何啟用函式 比如下面這個ReLU可以由如此的Maxout得到 選擇不同的$w$和$b$可以做到 你可能會問這樣不就有的節點訓練不到了嗎?因為有些節點的權值為0等於從網路中去除了。其實只是部分資料上此節點為0,但是我們有大量資料,總有資料可以訓練到這個節點。所以 $Maxout$ 需要比 $ReLU$ 更大的資料量才能訓練好這個網路。 #### 更新學習速率 ##### RMSProp 屬於之前線上性模型中提到的$Adagrad$演算法的變形 $$w^1 \longleftarrow w^0 - \frac{\eta}{\sigma^0}g^0 \qquad \sigma^0=g^0$$ $$w^2 \longleftarrow w^1 - \frac{\eta}{\sigma^1}g^1 \qquad \sigma^1=\sqrt{\alpha(\sigma^0)^2+(1-\alpha)(g^1)^2}$$ $$w^3 \longleftarrow w^2 - \frac{\eta}{\sigma^2}g^2 \qquad \sigma^2=\sqrt{\alpha(\sigma^1)^2+(1-\alpha)(g^2)^2}$$ $$......$$ $$w^{t+1} \longleftarrow w^t - \frac{\eta}{\sigma^t}g^t \qquad \sigma^t=\sqrt{\alpha(\sigma^{t-1})^2+(1-\alpha)(g^t)^2}$$ 一個固定的learning rate除以一個$\sigma$(在第一個時間點,$\sigma$就是第一個算出來GD的值),在第二個時間點,你算出來一個$g^1$和 $\sigma^2$(你可以去手動調一個$\alpha$值,把$\alpha$值調整的小一點,說明你傾向於相信新的gradient告訴你的這個error surface的平滑或者陡峭的程度)。 ##### Momentum 參考了物理世界慣性的概念,遇到一個小山坡時可以通過慣性翻過,從而越過區域性最優點。 在演算法中只參考上一次的速度,因為上一次的速度已經包含了之前所有的速度。 步驟: 1. 選擇一個初始位置 $\theta^0$ 和初始速度 $v^0=0$ 2. 計算在 $\theta^0$ 處的梯度$\Delta L(\theta^0)$ 3. $v^1=\lambda v^0-\eta\Delta L(\theta^0)$ 4. $\theta^0= \theta^1+v^1$ 5. 如此往復 ##### Adam $RMSProp$和$Momentum$的結合。有興趣的朋友直接看圖吧。 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200401235312204.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzkwMTIyMQ==,size_16,color_FFFFFF,t_70) ### 在train上改進(過擬合) ##### Early Stopping 我們需要的是測試集錯誤最小,而不是訓練集,如果測試集的Loss上升,則需要立刻停止訓練,但是如果將測試集加入訓練則會導致測試結果不客觀。這時我們可以引入驗證集來解決。當訓練時驗證集Loss上升則停止訓練。 ##### Regularization 和線性模型一樣,我們需要在原來的$loss function$加入正則化,讓得到的結果更加平滑。 常見的有$L_1-norm$(一次式)和$L_2-norm$(二次式) ##### Dropout ###### 如何訓練 在訓練時的時候,每一次引數更新之前,對network裡面的每個神經元(包括輸入層),做取樣(sampling)。 每個神經元會有p%的可能性會被丟掉,跟著的 $w$ 也會被丟掉。 ###### 解釋 你在訓練時,加上dropout,你會看到在訓練集上結果會變得有點差(因為某些神經元不見了),但是dropout真正做的事就是讓你測試集越做越好。 假設有$m$個神經元,就可以訓練 $2^m$ 個神經網路結構,每個網路的偏差雖然很大,但是最後平均下來還是很準的(這個又要回到我們線上性模型中說的 $varience$ 和 $bias$ 問題)。 dropout其實是用了模型融合(model essemble)的思想,訓練了很多模型最後加權得到最終的結果。 ###### 在testing上注意兩件事情: - 第一件事情就是在testing上不做dropout。 - 在dropout的時候,假設dropout rate在training是p%,all weights都要乘以$(1-p\%)$ 關於為什麼要乘$(1-p\%)$,舉一個簡單的例子: # 總結 到此神經網路已經介紹得差不多了,你可能會說,就這,就這?其實神經網路也不是什麼深奧的東西,本質上就是一個有著數千個引數的模型,和最簡單的線性模型一樣,也是通過最常規的方法——梯度下降求解。當然,其中也涉及了一些挺玄學(只可意會,不可言傳,當然也是我的數學功底不夠,無法準確描述)的方法。 上一篇:[機器學習筆記(1)——線性迴歸](https://blog.csdn.net/weixin_43901221/article/details/105211639) 下一篇:可能會講一講CNN或者神經網路中神經元的來源——logistic迴歸(未開始寫=。=) (如果覺得有用請點個