1. 程式人生 > >CS231n 卷積神經網路與計算機視覺 6 資料預處理 權重初始化 規則化 損失函式 等常用方法總結

CS231n 卷積神經網路與計算機視覺 6 資料預處理 權重初始化 規則化 損失函式 等常用方法總結

1 資料處理

首先註明我們要處理的資料是矩陣X,其shape為[N x D] (N =number of data, D =dimensionality).

1.1 Mean subtraction 去均值

去均值是一種常用的資料處理方式.它是將各個特徵值減去其均值,幾何上的展現是可以將資料的中心移到座標原點,Python中的程式碼是 X -= np.mean(X, axis = 0). 對於影象處理來說,每個畫素的值都需要被減去平均值 ( X -= np.mean(X)), 也可以分別處理RGB三個通道。

1.2 Normalization 標準化

normalization是將矩陣X中的Dimensions都保持在相似的變化範圍之內,有兩種實現形式: 1. 先使用上一步,使均值為0,然後除以標準差X /= np.std(X, axis = 0)

2. 在資料不再同一範圍,而且各個維度在同一範圍內對演算法比較重要時,可以將其最大最小值分別縮放為1和-1. 對於影象處理而言因為一般資料都在0-255之間所以不用再進行這一步了。 下面是資料處理的方式對比:這裡寫圖片描述

1.3 PCA和whitening

1.3.1 PCA

由於計算需要,需要實現進行前面所說的均值0化。 PCA要做的是將資料的主成分找出。流程如下: 1. 計算協方差矩陣 2. 求特徵值和特徵向量 3. 座標轉換 4. 選擇主成分 首先我們需要求出資料各個特徵之間的協方差矩陣,以得到他們之間的關聯程度,Python程式碼如下:

# Assume input data matrix X of size [N x D]
X -= np.mean(X, axis = 0) # zero-center the data (important)
cov = np.dot(X.T, X) / X.shape[0] # get the data covariance matrix,公式含義可按照協方差矩陣的定義得到
  • 1
  • 2
  • 3

其中得到的矩陣中的第(i,j)個元素代表第i列和第j列的協方差,對角線代表方差。協方差矩陣是對稱半正定矩陣可以進行SVD分解:

U,S,V = np.linalg.svd(cov)
  • 1

U 的列向量是特徵向量, S 是對角陣其值為奇異值也是特徵值的平方.奇異值分解的直觀展示:這裡寫圖片描述 具體可以看這篇部落格麻省理工的公開課。 我們可以用特徵向量(正交且長度為1可以看做新座標系的基)右乘X(相當於旋轉座標系)就可以得到新座標下的無聯絡(正交)的特徵成分:

Xrot = np.dot(X, U) # decorrelate the data
  • 1

注意上面使用的np.linalg.svd()已經將特徵值按照大小排序了,這裡僅需要取前幾列就是取前幾個主要成分了(實際使用中我們一般按照百分比取),程式碼:

Xrot_reduced = np.dot(X, U[:,:100]) # Xrot_reduced becomes [N x 100]
  • 1

1.3.2 白化

白化要做的就是在PCA的基礎上再除以每一個特徵的標準差,以使其normalization,其標準差就是奇異值的平方根:

# whiten the data:
# divide by the eigenvalues (which are square roots of the singular values)
Xwhite = Xrot / np.sqrt(S + 1e-5)
  • 1
  • 2
  • 3

但是白化因為將資料都處理到同一個範圍內了,所以如果原始資料有原本影響不大的噪聲,它原本小幅的噪聲也會放大到與全域性相同的範圍內了。 另外我們為了防止出現除以0的情況在分母處多加了0.00001,如果增大他會使噪聲減小。 白化之後得到是一個多元高斯分佈。 上面兩種處理的結果如下:這裡寫圖片描述 可以看出經過pca的去關聯操作,將原始資料的座標旋轉,並且可以看出x方向的資訊量比較大,如果只選一個特徵,那麼就選橫軸方向的特徵,經過白化之後資料進入了相同的範圍。 下面以處理之前提到過的CIFAR-10為例,看PCA和Whitening的作用:這裡寫圖片描述 左邊是原始圖片,每張圖片都是一個3072維的一行向量,經過PCA之後選取144維最重要的特徵(左2),將特徵轉化到原來的座標系U.transpose()[:144,:]得到了降維之後的圖形(左3),圖形變模糊了,說明我們的主要資訊都是低頻資訊,關於高低頻的含義在下一段展示一下,圖片模糊了但是主要成分都還在,最後一個圖是白化之後再轉換座標系之後的結果。

1.3.3 影象的高頻分量和低頻分量

形象一點說:亮度或灰度變化激烈的地方對應高頻成分,如邊緣;變化不大的地方對於低頻成分,如大片色塊區畫個直方圖,大塊區域是低頻,小塊或離散的是高頻,一幅圖象,你戴上眼鏡,盯緊了一個地方看到的是高頻分量 摘掉眼鏡,眯起眼睛,模模糊糊看到的就是低頻分量。(參考了這篇文章) 上面的白化之後低頻分量被大大的減弱了,但是高頻分量卻留了下來。

1.3.4 注意事項

  1. CNN不需要進行PCA和白化,這裡只是普及資料預處理的方法。
  2. CNN只需要均值0化就行了
  3. 注意進行所有的預處理時訓練集、驗證集和測試集都要使用相同的處理方法 ,比如在減去均值時,三個資料集需要減去相同的值。

2 權重初始化

在訓練上面我們處理好的資料之前,還需要對神經網路的權重進行初始化。

2.1 為什麼不是0?

首先說明下,初始權重不能全為0.經過適當的資料預處理之後我們可以合理的認為大約有一般的權重是正的另一半是負的,我們可能認為他的均值可能為0,但是絕對不能將其全部都設為0,嚴格來說不能把所有的權重都設定為相同的值,以前在反向傳播中已經提到過,如果所有的權重相同,如下圖:這裡寫圖片描述

那麼所有的神經單元都會得到相同的結果,另外在求梯度時候得到的梯度也是全部都一樣(還可以看知乎的相關問題)。

2.2 小隨機數

如2.1所說,我們還是想讓權重的接近於0,那麼取一個很小的接近於0的隨機數可以麼?例如這樣設定:

W = 0.01* np.random.randn(D,H)
  • 1

這樣既滿足各個初始值不一樣又可以使其接近於零,但是這樣還是不好,如果你看過上面提到的部落格和知乎之後就會發現返現傳播的梯度大小是和權重的值成正比的,所以如果其值很小那麼得到的梯度也是很小的。小型網路也許還可以,但是通過幾層網路之後會產生啟用值的非均勻分佈: 如一個10層每層500個單元的神經網路,初始化設定為W = 0.01* np.random.randn(D,H),啟用函式為tanh,就會發現每層得到的啟用值如下:這裡寫圖片描述 可以看到後面基層啟用值全部都成了0.畢竟w乘以x然後經過啟用函式再經過乘以w得到的結果會越來越接近於0.梯度也會變的很小。 如果我們將其值變大些W = 1* np.random.randn(D,H),得到的結果又會變為:這裡寫圖片描述,所有的又接近於1和-1,那麼每個啟用函式的導數由接近於0了。到底該怎麼設定呢?看下面

2.3 方差校準

經驗告訴我們如果初始時每個單元的輸出都有著相似的分佈會使收斂速度增大。而上面使用隨機的方式會使得各個單元的輸出值的分佈產生較大的變化,新假設使用線性啟用函式,探究輸入與輸出的分佈的關係。 首先我們設輸入是x,xw的內積是s,現在看他們方差的關係:

Var(s)=Var(∑inwixi)=∑inVar(wixi)=∑in[E(wi)]2Var(xi)+E[(xi)]2Var(wi)+Var(xi)Var(wi)=∑inVar(xi)Var(wi)=(nVar(w))Var(x)

其中我們設x和w均值相同為0且相互獨立。得到的結果顯示,如果希望s與輸入變數x同分布就需要使w的方差為1/n,即:w = np.random.randn(n) / sqrt(n)這樣設定之後每層輸出值的均值、方差和分佈如下:這裡寫圖片描述 這是在啟用函式在tanh時,但是如果換做ReLU結果卻成了下面的樣子:這裡寫圖片描述 看出分佈又不一樣了。我們需要根據上面的過程做一個更加複雜的推導使各層的輸出分佈相似,最近的一篇文章 Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification by He et al 求探討了ReLU的初始化應該是w = np.random.randn(n) * sqrt(2.0/n) 這樣得到的分佈是:這裡寫圖片描述 不禁想說一句科學很神奇。 另外還有人推薦 Var(w)=2/(nin+nout) ninnout 是前面一層神經網路的單元數和後面一層神經網路的單元數量。 另外還有很多人有過探究,這是一個很火的領域:

Understanding the difficulty of training deep feedforward neural networks by Glorot and Bengio, 2010 Exact solutions to the nonlinear dynamics of learning in deep linear neural networks by Saxe et al, 2013 Random walk initialization for training very deep feedforward networks by Sussillo and Abbott, 2014 Delving deep into rectifiers: Surpassing human-level performance on ImageNet classification by He et al., 2015 Data-dependent Initializations of Convolutional Neural Networks by Krähenbühl et al., 2015 All you need is a good init, Mishkin and Matas, 2015 ……

2.4 Sparse initialization. 係數初始化

其思想是先將權重初始設定為全部都是0,但是為了避免2.1敘述的情況,打破初始對稱,每個神經單元只能隨機的與固定個數的神經單元連線(比如經典的選取10個的方法)。

2.5 截距的初始化

截距或者biase的初始化可以使用0,因為w的設定已經使對稱失效了,在使用ReLU時有人會設定為較小的數例如0.01,但是這樣設定會不會有好處還沒有確切的定論。

2.6 推薦的方法

推薦使用ReLU單元和w = np.random.randn(n) * sqrt(2.0/n的初始化設定方法。

2.7 Batch Normalization

這是一種近期才出現的技術,提出者是Ioffe 和Szegedy,效果不錯,連線在這裡arXiv。它強制將啟用值在訓練前設定為高斯分佈,他在全連線層和啟用函式層中間插入了一層Batch Normalization層. 現在batch normalization的使用已經比較廣泛了,具體設定方法請看前面連線的論文,它具有以下優點: 1. 提高了梯度的傳遞性 2. 可以允許更高的學習速率 3. 降低了對於初始值的依賴性 4. 以regularization的形式起作用,可能稍微會對dropout的需求 另外,Batch normailization可以被理解為在每層之前做一下預處理, 但是卻整合到了神經網路中去了。

3 Regularization 規則化

3.1 L2

L2 regularization可能是最常見的規則化方法了,其手段就是將每個w都加入一項12λw2

,這裡的1/2是為了在求導的時候能夠約去2,其作用相當於W += -lambda * W,讓w向0的方向線性降低。它傾向於使各個權重變得分散均勻,也就是傾向於使各個輸入值都可以被利用。

3.2 L1

L1是加入了λ|w|

項,其好處是可以得到稀疏矩陣,留住重要的輸入,去除噪音,L1可以和L2 混用這時也稱作Elastic net regularization。如果不是想明確特徵的選擇,一般L2的效果要比L1要好。

3.3 Max norm constraints

最大範數約束主要思路是安照正常進行update,只不過每次更新之後檢查其範數是否大約了設定值∥w⃗ ∥2<c

,c的經典取值是3或者4.有人說效果還可以。

3.4 Dropout

這是一種簡單高效常用的方法,與前面的三種方法互補,由 Srivastava等提出的。文章在這裡Dropout: A Simple Way to Prevent Neural Networks from Overfitting(PDF)。 這種方法的思想是在訓練時候只是一部分的神經單元工作,如圖:這裡寫圖片描述 神經單元可以被使用的概率是P(是一個超引數)或者是0,其測試的時候全部的神經元都是可以利用的,這時候相當於ensemble。 下面是一個三層網路的簡易過程:

""" Vanilla Dropout: Not recommended implementation (see notes below) """

p = 0.5 # probability of keeping a unit active. higher = less dropout

def train_step(X):
  """ X contains the data """

  # forward pass for example 3-layer neural network
  H1 = np.maximum(0, np.dot(W1, X) + b1)#相當於將矩陣的最小值變為0,where(x>0,0)
  U1 = np.random.rand(*H1.shape) < p # first dropout mask注意星號哦
  H1 *= U1 # drop!注意*=
  H2 = np.maximum(0, np.dot(W2, H1) + b2)
  U2 = np.random.rand(*H2.shape) < p # second dropout mask
  H2 *= U2 # drop!
  out = np.dot(W3, H2) + b3

  # backward pass: compute gradients... (not shown)
  # perform parameter update... (not shown)

def predict(X):
  # ensembled forward pass
  H1 = np.maximum(0, np.dot(W1, X) + b1) * p # NOTE: scale the activations注意生成了一個p
  H2 = np.maximum(0, np.dot(W2, H1) + b2) * p # NOTE: scale the activations
  out = np.dot(W3, H2) + b3

上面我們沒有對輸入層進行dropout(也可以做),輸出層加入了p這一乘積項,這是因為訓練的時候某個神經單元被使用的概率是p,如果他的輸出是x那麼他訓練時輸出值的期望只是px,所以在預測階段要乘以p,但是並不推薦這樣做。因為在預測階段進行操作無異於增加了預測響應時間。我問使用 inverted dropout來解決這個問題。 其方法是在預測時不再乘以p,而是在預測時除以p。

""" 
Inverted Dropout: Recommended implementation example.
We drop and scale at train time and don't do anything at test time.
"""

p = 0.5 # probability of keeping a unit active. higher = less dropout

def train_step(X):
  # forward pass for example 3-layer neural network
  H1 = np.maximum(0, np.dot(W1, X) + b1)
  U1 = (np.random.rand(*H1.shape) < p) / p # first dropout mask. Notice /p!這是重點,重點,點,點,點
  H1 *= U1 # drop!
  H2 = np.maximum(0, np.dot(W2, H1) + b2)
  U2 = (np.random.rand(*H2.shape) < p) / p # second dropout mask. Notice /p!
  H2 *= U2 # drop!
  out = np.dot(W3, H2) + b3

  # backward pass: compute gradients... (not shown)
  # perform parameter update... (not shown)

def predict(X):
  # ensembled forward pass
  H1 = np.maximum(0, np.dot(W1, X) + b1) # no scaling necessary
  H2 = np.maximum(0, np.dot(W2, H1) + b2)
  out = np.dot(W3, H2) + b3

相關書籍: 1. Dropout paper by Srivastava et al. 2014. 2. Dropout Training as Adaptive Regularization: “we show that the dropout regularizer is first-order equivalent to an L2 regularizer applied after scaling the features by an estimate of the inverse diagonal Fisher information matrix”.

3.5 Theme of noise in forward pass

類似於dropout還有很多類似的方法,比如dropconnect.

3.6 bias regularization

bias不與輸入變數直接相乘,不能控制資料對最終目標的影響,所以表示一般不用regularization,但是它的數量相對於w很少,約束下也不會有太大的影響。

3.7 Per-layer regularization.

很少有這樣對每層加不同約束的。

3.8 應用

  1. 最常見的是使用一個使用cv優化之後的單獨的L2約束
  2. 可以使用dropout之後用L2,p可以選用0.5也可以選別的值,但是需要在驗證集上檢驗下。

4 損失函式 loss functions

我們已經考慮loss function裡的regularization loss 還有一部分 data loss還沒有考慮.損失函式是考慮每個案例的損失的平均值L=1N∑iLi

,這裡設神經網路的啟用函式為f=f(xi;W)

4.1 分類問題

我們目前討論的分類問題一般只有一個正確答案,常用的有svm和softmax的損失函式。svm的分類損失函式是:

Li=∑j≠yimax(0,fj−fyi+1)

或者

Li=∑j≠yimax(0,fj−fyi+1)2

softmax的損失函式是:

Li=−log(efyi∑jefj)

4.1.2大量類別問題

在進行文字分類等有很多類別的時候可以用Hierarchical Softmax的方法,其栗子在這裡,他先建立一棵類別樹,每一個節點用於softmax,樹的結構對分類效果影響很大,需要具體問題具體分析。

4.1.3多屬性類別

同一個物體可能有多重屬性,其類別也就可能有多個,解決方法有: 1. 多個二分類器,其損失函式為

Li=∑jmax(0,1−yijfj)

j代表類別,yij代表第i個example是否屬於j類(取1或者-1),fj是預測的score function。 2. 建立多個logistic regression。

Li=∑jyijlog(σ(fj))+(1−yij)log(1−σ(fj))

其中σ是sigmoid函式,對f求導得到:∂Li/∂fj=yij−σ(fj)

4.2 regression迴歸

L2形式:

Li=∥f−yi∥22

l2求導方便 L1形式:

Li=∥f−yi∥1=∑j∣fj−(yi)j∣

設δi,j是i-th樣本的第j個特徵相對於真實值的差距,這時∂Li/∂fj要麼等於δi,j的L2範數,要麼等於sign(δi,j),所以對得分函式的梯度一般要麼直接使用delta的比例,要麼修正之後只整合sign的部分。

4.3 注意

  1. L2 loss的求解比穩定的損失如softmax的損失要更難優化;
  2. softmax的得分多少並不重要,只有在量級合適的時候才有意義;
  3. L2 loss 因為outliers可能會引入巨大的梯度所以可能不穩定
  4. 面對regression先看能不能化為classification
  5. 對regression的L2 loss不宜使用dropout。

4.4 Structured prediction.

結構化預測(structured prediction)是由SVM發展而來的。,結構化問題的例子有很多:給定一個句子,找出它對應的依存樹(dependency tree);對一個圖進行分割(image segmentation)等。結構化預測通過修改SVM的約束條件以及目標函式,將SVM從二分類問題擴充套件到可以預測結構化問題。這類問題一般很難用純數學去計算,具體內容不再本課程範圍內,這裡有一篇相關的文章,及維基百科