1. 程式人生 > >斯坦福cs231n學習筆記(8)------神經網路訓練細節(資料預處理、權重初始化)

斯坦福cs231n學習筆記(8)------神經網路訓練細節(資料預處理、權重初始化)

神經網路訓練細節系列筆記:

這一篇,我們將繼續介紹神經網路訓練細節。

一、Data Preprocessing(資料預處理)


如圖是原始資料,資料矩陣X有三種常見的資料預處理形式,其中我們假定X的大小為[N×D](N是資料的數量,D是它們的維數)。

  • 歸一化處理(normalized data)
    22.png
    如上圖所示,歸一化處理是指每個維度都通過標準偏差來進行縮放或者確保每個維度最大值和最小值在-1到1之間等等,紅線表示資料的範圍,中間長度不等,右邊長度相等。在影象處理中,歸一化並不常用。

  • 零中心化處理

    零中心化處理是指減去每個維度的平均值,進而使得資料是以零為中心的。資料雲集中在原點的周圍。在影象處理中,零中心化處理是一種常用的資料預處理的方式。

  • PCA and Whitening(PCA演算法和白化處理)
    PCA和白化是資料預處理的另一種方式。在這個過程中,應用PCA演算法將協方差矩陣變成對角矩陣,或者對資料進行白化處理,那意味著在PCA處理後對資料進行壓縮,使協方差矩陣變成單位矩陣,這種預處理方式在機器學習中經常用到。

以上三種資料預處理的方法在影象處理中並不常用,在影象處理中常見的是均值中心化處理,以32*32*3的CIFAR影象為例,有兩種方式實現:
減去均值影象
經過計算後得到一個32*32*3的均值影象,用每張影象減去均值影象進行中心化處理,從而獲得更好的訓練效果。
減去單通道均值
這種資料預處理方式常常用在VGGNet中,在紅綠藍三色通道中分別計算,分別得到3個數值。這種預處理方式非常常用,因為我們只需要關心三個數值,而不用考慮上一方法中均值影象中的那個均值影象陣列。

二、Weight Initialization(權重初始化)

w(權重)的初始化問題也是早期神經網路發展不好的原因,是人們不重視的一個very very very重要的引數。首先,如果不進行初始化,那麼在w=0的情況下所有的神經元都是一樣的,在反向傳播時的梯度都是一樣的,這個網路是不能工作的,所有的神經元進行相同的計算,這不是一個很好的方式。因此,人們用很小的隨機數值代替,隨機數值是從標準差為0.01的高斯公式中隨機抽取,這是w初始化的一種方式。

但是這種初始化方式是存在問題的,應用層數少的神經網路還可以,但是隨著層數的增加,這種簡單的初始化方法是無效的。下面將詳細講解什麼方法無效以及Why,How。我們從程式碼、視覺化資料來分析w的初始化過程。

D = np.random.randn[(1000,500)
hidden_layer_sizes = [500]*10
nornlinearities = ['tanh']*len(hidden_layer_sizes)

我們要做的是用高斯分佈來初始化權值w,然後進行網路傳播,所以定義一個for迴圈,迴圈進行傳播,即在一些相同尺寸的隱藏層中進行一系列計算。

act = {'relu':lambda x:np.maximum(0,x), 'tanh':lambda x:np.tanh(x)}
Hs = {}
for i in xrange(len(hidden_layer_sizes)):
     X = D if i == 0 else Hs[i-1]
     fan_in = X.shape[1]
     fan_out = hidden_layer_sizes[i]
     W = np.random.randn(fan_in,fan_out) * 0.01
     H = np.dot(X,W)
     H = act[nonlinearities[i]](H)
     Hs[i] = H

So,我們希望更加了解隱藏層中的神經元會如何啟用,因此我們著重關注均差和標準差,同時,我們將均差和標準差用柱狀圖繪製出來,讓所有的資料通過網路,然後觀察第五、第六或第七層上的權值,用柱狀圖顯示出來。

print 'input layer had mean %f and std %f' % (np.mean(D), np.std(D))
layer_means = [np.mean(H) for i,H in Hs.iteritems()]
layer_stds = [np.std(H) for i,H in Hs.iteritems()]
for i,H in Hs.itemritems():
      print ' hidden layer %d had mean %f and std %f' % (i+1, layer_means[i], layer_stds[i])
plt.figure()
plt.subplot(121)
plt.plot(Hs.keys(), layer_means, 'ob-')
plt.title('layer mean')
plt.subplot(122)
plt.plot(Hs.keys(), layer_means, 'or-')
plt.title('layer std')

plt.figure()
for i,H in Hs.iteritems():
      plt.subplot(1,len(Hs),i+1)
      plt.hist(H.ravel(),30,range=(-1,1))

那麼,我們採用標準差為0.01的高斯公式的策略初始化w:

由圖片中,我們可以看到,一開始輸入的均值是0,標準差是1,在前向傳播的過程中,我們觀察經過10層網路之後的情況,我們使用的是tanh函式,tanh函式關於原點對稱的,所以均值會歸於0左右,再來看看方差,一開始是1,在接下來的層中,變成0.2,0.04,直線下降至0,所以神經元的方差會降到0。看柱狀圖,第一張是合理的,我們的資料處於-1到1之間,隨後這些資料分佈開始“坍塌”,最終只分布在0上,在10層網路上使用這種初始化方法,最終所有以tanh為啟用函式的神經元,輸出都是0,這是為什麼?
A:輸入X是小量數值,那麼w的梯度也是小量數值,w*x的啟用函式計算出的結果對梯度的疊加是無影響的,在反向傳播過程中,通過鏈式法則不斷的乘w,最終得到的梯度非常小,幾乎為0,這時就出現了梯度彌散(消失)的問題。使用標準差為0.01的高斯分佈策略進行w初始化,我們會發現梯度的量級不斷縮小,所以我們可以嘗試另一種方式來優化w初始化,與其將數值規整到-1和1之間,我們可以嘗試一些其他的尺度來初始化w矩陣,*使用1.0來代替0.01。那麼我們來看下此時的輸出情況:

由影象可以看出,發生了另一個奇特的事情,因為我們“走過頭”了。由於數值設定的過高,所有的tanh函式輸出不是1就是-1,這意味著所有傳遞的數值都過於飽和了。因為w過大,正向傳播後的數值就會變得非常大。那麼在反向傳播中計算的梯度就會趨向0,然後使得我們的網路無法工作,即使訓練時間加長,損失函式也根本不會變,因為所有的神經元都飽和了,無法進行反向傳播,權值得不到更新。基於此,我們沒有必要在1.0和0.01之間進行手工測試。

2010年,有一篇是由Glorot等人寫的論文,我們稱之為Xavier初始化,他們關注了神經元的方差表示式,對每個神經元的輸入進行開根號,如果有很多的輸入,最終會得到較小的權值,從直觀上來看,這麼做是有意義的。


因為加權和中被算入的量更多了,而且希望它們之間的相關性降低。如果輸入很少,那麼我們需要較大的權值,因為其中僅有一小部分希望它們的方差是1。所以,這種思路的核心就是隻關注單個神經元,不包括啟用函式,僅僅是線性的神經元。如果我們輸入的是高斯分佈的資料,並且希望線性神經元方差是1,那麼我們應該用這種方法對w進行初始化。從影象上看,數值的分佈更有意義了 ,從-1到1之間的tanh單元的直方圖,數值都在作用區域內,沒有出現飽和的情況,這種方式效果也不是非常好,從一個直方圖可以看出,出現了一個下凹,其原因是這篇論文並未考慮tanh的非線性。tanh函式的非線性,將資料的方差改變,這將影響資料方差的分佈。So,這是一個靠譜的初始化方式,可以應用到神經網路中來,比起設定0.01要好得多。但是,雖然這種方法在tanh為啟用函式的網路中奏效,但是換了ReLU,ReLU並不奏效,反而方差下降的更快,ReLU神經元分佈越來越差,並趨於0,進而越來越多的神經元未被啟用。


從ReLU的資料分佈中,我們可以看到,在第一層中,能看出一些分佈,但是在之後的幾層中,分佈越來越窄,並趨於0,也就說在這種初始化方法下,越來越多的神經元沒有啟用。所以這種初始化方式應用在ReLU網路中,並沒有什麼好的結果。回頭看一下已tanh函式為啟用函式的神經元,Glorot等人當年並沒有討論非線性和ReLU神經元的情況,所以在計算加權和後,讓結果經過一個ReLU的啟用函式,由ReLU神經元的資料分佈可以看出,一半的貢獻被置0了,從直觀上來看,輸出的分佈是方差的一半。所以應用ReLU在高斯分佈中應該額外考慮因數2,最終結果就會收斂;若沒有引入因數2,啟用函式輸出的分佈就會以指數倍收縮。如果你在實際中使用ReLU神經元,那麼這裡提到的這種初始化方法才是合理的。

In a word,w初始化問題在實際中是需要好好斟酌的,由於這是一種策略性的東西,所以才使得神經網路走這麼遠。可能人們認為調參不會很難,這也使得研究一種合理的初始化方法一直是一個活躍的研究領域,這裡給大家提供一些論文,大量的論文介紹不同的初始化方法。它們沒有一個標準的初始化公式,使用何種初始化也是資料驅動的。