史丹佛CS231n課程筆記純乾貨2

marsjhao發表於2020-04-06

11. 神經網路的資料預處理

均值減法(Mean subtraction是預處理最常用的形式。它對資料中每個獨立特徵減去平均值,從幾何上可以理解為在每個維度上都將資料雲的中心都遷移到原點。在numpy中,該操作可以通過程式碼X -=np.mean(X, axis=0)實現。而對於影像,更常用的是對所有畫素都減去一個值,可以X -= np.mean(X)實現,也可以在3個顏色通道上分別操作。

歸一化(Normalization是指將資料的所有維度都歸一化,使其數值範圍都近似相等。有兩種常用方法可以實現歸一化。第一種是先對資料做零中心化(zero-centered)處理,然後每個維度都除以其標準差,實現程式碼為X /= np.std(X,axis=0)。第二種方法是對每個維度都做歸一化,使得每個維度的最大和最小值是1和-1。這個預處理操作只有在確信不同的輸入特徵有不同的數值範圍(或計量單位)時才有意義,但要注意預處理操作的重要性幾乎等同於學習演算法本身。在影像處理中,由於畫素的數值範圍幾乎是一致的(都在0-255之間),所以進行這個額外的預處理步驟並不是很必要。

PCA和白化(Whitening)是另一種預處理形式。在這種處理中,先對資料進行零中心化處理,然後計算協方差矩陣,它展示了資料中的相關性結構。

X -= np.mean(X, axis = 0) # 對資料進行零中心化(重要)
cov = np.dot(X.T, X) / X.shape[0] # 得到資料的協方差矩陣
U,S,V =np.linalg.svd(cov)
Xrot =np.dot(X,U) # 對資料去相關性
np.linalg.svd的一個良好性質是在它的返回值U中,特徵向量是按照特徵值的大小排列的。這個操作也被稱為主成分分析( Principal Component Analysis 簡稱PCA)降維:

Xrot_reduced = np.dot(X,U[:,:100]) #Xrot_reduced 變成 [N x 100]

白化(whitening。白化操作的輸入是特徵基準上的資料,然後對每個維度除以其特徵值來對數值範圍進行歸一化。該變換的幾何解釋是:如果資料服從多變數的高斯分佈,那麼經過白化後,資料的分佈將會是一個均值為零,且協方差相等的矩陣。該操作的程式碼如下:

# 對資料進行白化操作:
# 除以特徵值
Xwhite = Xrot / np.sqrt(S+ 1e-5)

PCA和白化主要是為了介紹的完整性,實際上在卷積神經網路中並不會採用這些變換

常見錯誤。進行預處理很重要的一點是:任何預處理策略(比如資料均值)都只能在訓練集資料上進行計算,演算法訓練完畢後再應用到驗證集或者測試集上。例如,如果先計算整個資料集影像的平均值然後每張圖片都減去平均值,最後將整個資料集分成訓練/驗證/測試集,那麼這個做法是錯誤的。應該怎麼做呢?應該先分成訓練/驗證/測試集,只是從訓練集中求圖片平均值,然後各個集(訓練/驗證/測試集)中的影像再減去這個平均值。

12. 神經網路的權重初始化

錯誤:全零初始化。因為如果網路中的每個神經元都計算出同樣的輸出,然後它們就會在反向傳播中計算出同樣的梯度,從而進行同樣的引數更新神經元之間就失去了不對稱性的源頭。

小隨機數初始化。解決方法就是將權重初始化為很小的數值,以此來打破對稱性。小隨機數權重初始化的實現方法是:W = 0.01 * np.random.randn(D,H)。每個神經元的權重向量都被初始化為一個隨機向量,而這些隨機向量又服從一個多變數高斯分佈,這樣在輸入空間中,所有的神經元的指向是隨機的。

使用1/sqrt(n)校準方差。隨著輸入資料量的增長,隨機初始化的神經元的輸出資料的分佈中的方差也在增大。我們可以除以輸入資料量的平方根來調整其數值範圍,這樣神經元輸出的方差就歸一化到1了。建議將神經元的權重向量初始化為:w =np.random.randn(n) / sqrt(n)。其中n是輸入資料的數量。

偏置(biases)的初始化。通常將偏置初始化為0。

實踐。當前的推薦是使用ReLU啟用函式,並且使用w =np.random.randn(n) * sqrt(2.0/n)來進行權重初始化。

批量歸一化(Batch Normalization)。該方法減輕瞭如何合理初始化神經網路這個棘手問題帶來的頭痛。在實現層面,應用這個技巧通常意味著全連線層(或者是卷積層,後續會講)與啟用函式之間新增一個BatchNorm。在實踐中,使用了批量歸一化的網路對於不好的初始值有更強的魯棒性。最後一句話總結:批量歸一化可以理解為在網路的每一層之前都做預處理,只是這種操作以另一種方式與網路整合在了一起。

13. 神經網路的正則化

L2正則化可能是最常用的正則化方法了。可以通過懲罰目標函式中所有引數的平方將其實現。即對於網路中的每個權重w,向目標函式中增加一個

L1正則化是另一個相對常用的正則化方法。對於每個w我們都向目標函式增加一個L1L2正則化也可以進行組合:,這也被稱作Elastic net regularizaton。在實踐中,如果不是特別關注某些明確的特徵選擇,一般說來L2正則化都會比L1正則化效果好。

最大正規化約束(Max norm constraints另一種形式的正則化是給每個神經元中權重向量的量級設定上限,並使用投影梯度下降來確保這一約束。即使在學習率設定過高的時候,網路中也不會出現數值爆炸,這是因為它的引數更新始終是被限制著的。

隨機失活(Dropout),隨機失活的實現方法是讓神經元以超引數的概率被啟用或者被設定為0

在測試過程中不使用隨機失活,可以理解為是對數量巨大的子網路們做了模型整合(model ensemble),以此來計算出一個平均的預測。

14. 神經網路的損失函式

分類問題中,一個最常見的損失函式就是SVM(是Weston Watkins 公式):有些學者的論文中指出平方折葉損失(即使用)演算法的結果會更好。第二個常用的損失函式是Softmax分類器,它使用交叉熵損失:

迴歸問題中,對於某個樣本,L2正規化計算如下: L1正規化則是要將每個維度上的絕對值加起來:

注意L2損失比起較為穩定的Softmax損失來,其最優化過程要困難很多。所以在面對一個迴歸問題時,先考慮將輸出變成二值化是否真的不夠用。

當面對一個迴歸任務,首先考慮是不是必須這樣。一般而言,儘量把你的輸出變成二分類,然後對它們進行分類,從而變成一個分類問題。

15. 學習過程檢查

訓練期間第一個要跟蹤的數值就是損失值,它在前向傳播時對每個獨立的批資料進行計算。下圖展示的是隨著損失值隨時間的變化,尤其是曲線形狀會給出關於學習率設定的情況:

右圖顯示了一個典型的隨時間變化的損失函式值,而且指出了批資料的數量可能有點太小(因為損失值的噪音很大)。損失值的震盪程度和批尺寸(batch size)有關,當批尺寸為1,震盪會相對較大。當批尺寸就是整個資料集時震盪就會最小,因為每個梯度更新都是單調地優化損失函式(除非學習率設定得過高)。

在訓練集準確率和驗證集準確率中間的空隙指明瞭模型過擬合的程度。在圖中,藍色的驗證集曲線顯示相較於訓練集,驗證集的準確率低了很多,這就說明模型有很強的過擬合。遇到這種情況,就應該增大正則化強度(更強的L2權重懲罰,更多的隨機失活等)或收集更多的資料。另一種可能就是驗證集曲線和訓練集曲線如影隨形,這種情況說明你的模型容量還不夠大:應該通過增加引數數量讓模型容量更大些。

16. 神經網路的引數更新

普通更新x += -learning_rate* dx

動量(Momentum)更新

v = mu *v - learning_rate * dx # 與速度融合
x += v # 與位置融合

在這裡引入了一個初始化為0的變數v和一個超引數mu。說得不恰當一點,這個變數(mu)在最優化的過程中被看做動量(一般值設為0.9,但其物理意義與摩擦係數更一致。這個變數有效地抑制了速度,降低了系統的動能,不然質點在山底永遠不會停下來。通過交叉驗證,這個引數通常設為[0.5,0.9,0.95,0.99]中的一個。和學習率隨著時間退火(下文有討論)類似,動量隨時間變化的設定有時能略微改善最優化的效果,其中動量在學習過程的後階段會上升。一個典型的設定是剛開始將動量設為0.5而在後面的多個週期(epoch)中慢慢提升到0.99

通過動量更新,引數向量會在任何有持續梯度的方向上增加速度。

Nesterov動量

Nesterov動量。既然我們知道動量將會把我們帶到綠色箭頭指向的點,我們就不要在原點(紅色點)那裡計算梯度了。使用Nesterov動量,我們就在這個“向前看”的地方計算梯度。

v_prev = v # 儲存備份
v = mu * v -learning_rate * dx # 速度更新保持不變
x += -mu *v_prev + (1 + mu) * v # 位置更新變了形式

學習率退火

隨步數衰減每進行幾個週期就根據一些因素降低學習率。

指數衰減。數學公式是,其中是超引數,t是迭代次數(也可以使用週期作為單位)。

1/t衰減的數學公式是,其中是超引數,t是迭代次數。

在實踐中,我們發現隨步數衰減的隨機失活(dropout)更受歡迎,因為它使用的超引數(衰減係數和以週期為時間單位的步數)比更有解釋性。最後,如果你有足夠的計算資源,可以讓衰減更加緩慢一些,讓訓練時間更長些

逐引數適應學習率方法

Adagrad是一個由Duchi提出的適應性學習率演算法

# 假設有梯度和引數向量x
cache += dx**2
x += - learning_rate *dx / (np.sqrt(cache) + eps)

Adagrad的一個缺點是,在深度學習中單調的學習率被證明通常過於激進且過早停止學習。

RMSprop

cache =  decay_rate * cache + (1 - decay_rate) * dx**2
x += - learning_rate *dx / (np.sqrt(cache) + eps)

在上面的程式碼中,decay_rate是一個超引數,常用的值是[0.9,0.99,0.999]

AdamAdam是最近才提出的一種更新方法,它看起來像是RMSProp的動量版。簡化的程式碼是下面這樣:

m = beta1*m + (1-beta1)*dx
v = beta2*v + (1-beta2)*(dx**2)
x += - learning_rate *m / (np.sqrt(v) + eps)

論文中推薦的引數值eps=1e-8, beta1=0.9, beta2=0.999。在實際操作中,我們推薦Adam作為預設的演算法,一般而言跑起來比RMSProp要好一點。

各優化器優化過程演示:


17. 超引數調優

神經網路最常用的設定有:初始學習率。學習率衰減方式(例如一個衰減常量)。正則化強度(L2懲罰,隨機失活強度)。比起交叉驗證最好使用一個驗證集

模型整合

在實踐的時候,有一個總是能提升神經網路幾個百分點準確率的辦法,就是在訓練的時候訓練幾個獨立的模型,然後在測試的時候平均它們預測結果。整合的模型數量增加,演算法的結果也單調提升(但提升效果越來越少)。還有模型之間的差異度越大,提升效果可能越好。

同一個模型,不同的初始化。使用交叉驗證來得到最好的超引數,然後用最好的引數來訓練不同初始化條件的模型。這種方法的風險在於多樣性只來自於不同的初始化條件。

18. 卷積神經網路基礎

與常規神經網路不同,卷積神經網路的各層中的神經元是3維排列的:寬度高度深度(這裡的深度指的是啟用資料體的第三個維度,而不是整個網路的深度,整個網路的深度指的是網路的層數)。

左邊是一個3層的神經網路。右邊是一個卷積神經網路,圖例中網路將它的神經元都排列成3個維度(寬、高和深度)。卷積神經網路的每一層都將3D的輸入資料變化為神經元3D的啟用資料並輸出。

19. 卷積神經網路的結構

一個簡單的卷積神經網路是由各種層按照順序排列組成,網路中的每個層使用一個可以微分的函式將啟用資料從一個層傳遞到另一個層。卷積神經網路主要由三種型別的層構成:卷積層匯聚(Pooling)層全連線層(全連線層和常規神經網路中的一樣)。通過將這些層疊加起來,就可以構建一個完整的卷積神經網路。

卷積層

卷積層的引數是有一些可學習的濾波器集合構成的。每個濾波器在空間上(寬度和高度)都比較小,但是深度和輸入資料一致。

直觀地來說,網路會讓濾波器學習到當它看到某些型別的視覺特徵時就啟用,具體的視覺特徵可能是某些方位上的邊界,或者在第一層上某些顏色的斑點,甚至可以是網路更高層上的蜂巢狀或者車輪狀圖案。

在每個卷積層上,我們會有一整個集合的濾波器(比如12個),每個都會生成一個不同的二維啟用圖。將這些啟用對映在深度方向上層疊起來就生成了輸出資料。

區域性連線:在處理影像這樣的高維度輸入時,讓每個神經元都與前一層中的所有神經元進行全連線是不現實的。相反,我們讓每個神經元只與輸入資料的一個區域性區域連線。該連線的空間大小叫做神經元的感受野(receptive field),它的尺寸是一個超引數(其實就是濾波器的空間尺寸)。在深度方向上,這個連線的大小總是和輸入量的深度相等。需要再次強調的是,我們對待空間維度(寬和高)與深度維度是不同的:連線在空間(寬高)上是區域性的,但是在深度上總是和輸入資料的深度一致。

空間排列:上文講解了卷積層中每個神經元與輸入資料體之間的連線方式,但是尚未討論輸出資料體中神經元的數量,以及它們的排列方式。3個超引數控制著輸出資料體的尺寸:深度(depth),步長(stride零填充(zero-padding

輸出資料體的空間尺寸為(W-F +2P)/S+1,在計算上,輸入資料體的長和寬按照該公式計算,深度依賴於濾波器的數量。

匯聚層(池化層 pooling)

最大匯聚的效果比平均匯聚要好。

卷積神經網路通常是由三種層構成:卷積層,匯聚層(除非特別說明,一般就是最大值匯聚)和全連線層(fully-connected簡稱FC)。ReLU啟用函式也應該算是是一層,它逐元素地進行啟用函式操作。

最常見的卷積神經網路結構如下:

INPUT ->[[CONV -> RELU]*N -> POOL?]*M -> [FC -> RELU]*K -> FC

其中*指的是重複次數,POOL?指的是一個可選的匯聚層。其中N >=0,通常N<=3,M>=0,K>=0,通常K<3。例如,下面是一些常見的網路結構規律:

INPUT ->FC,實現一個線性分類器,此處N= M = K = 0

INPUT ->CONV -> RELU -> FC

INPUT ->[CONV -> RELU -> POOL]*2 -> FC -> RELU -> FC。此處在每個匯聚層之間有一個卷積層。

INPUT ->[CONV -> RELU -> CONV -> RELU -> POOL]*3 -> [FC -> RELU]*2-> FC。此處每個匯聚層前有兩個卷積層,這個思路適用於更大更深的網路,因為在執行具有破壞性的匯聚操作前,多重的卷積層可以從輸入資料中學習到更多的複雜特徵。

幾個小濾波器卷積層的組合比一個大濾波器卷積層好。

更多關於CNN的內容請移步這裡:深度學習之卷積神經網路CNN

相關文章