1. 程式人生 > >Deep learning系列(八)引數初始化

Deep learning系列(八)引數初始化

0. 引言

主成分分析與白化一節中介紹瞭如何對輸入資料進行預處理,在這節中介紹與之類似的另一個問題,引數初始化(Weight Initialization)。

在模型訓練之初,我們不知道引數的具體分佈,然而如果資料經過了合理的歸一化(normalization)處理後,對於引數的合理猜測是其中一半是正的,另一半是負的。然後我們想是不是把引數都初始化為0會是比較好的初始化?這樣做其實會帶來一個問題,經過正向傳播和反向傳播後,引數的不同維度之間經過相同的更新,迭代的結果是不同維度的引數是一樣的,嚴重地影響了模型的效能。

1. 小的隨機數

我們仍然想要引數接近於0,又不是絕對的0,一種可行的做法是將引數初始化為小的隨機數,這樣做可以打破對稱性(symmetry breaking)。python程式碼如下:

nn_input_dim = 2
nn_hdim = 3
W = 0.001* np.random.randn(nn_input_dim,nn_hdim)

其中randn從均值為0,標準差是1的高斯分佈中取樣,這樣,引數的每個維度來自一個多維的高斯分佈。需要注意的是引數初始值不能取得太小,因為小的引數在反向傳播時會導致小的梯度,對於深度網路來說,也會產生梯度彌散問題,降低引數的收斂速度。

2. 將方差乘以1/sqrt(n)

引數隨機初始化為一個小的隨機數存在一個問題:一個神經元輸出的方差會隨著輸入神經元數量的增多而變大。對於有n個輸入單元的神經元來說,考慮χ2分佈,每個輸入的方差是1/n時,總的方差是1,因此,我們對每個輸入的標準差乘以1

/sqrt(n),每個神經元的引數初始化程式碼為:

w = np.random.randn(n) / sqrt(n)

其中n為這個神經元輸入的個數。這樣可以確保神經元的輸出有相同的分佈,提高訓練的收斂速度。

將上面初始化方案推廣到網路的一層,對於神經網路的第一層可以這樣初始化:

nn_input_dim = 2
nn_hdim = 3
w = np.random.randn(nn_input_dim,nn_hdim) / sqrt(nn_input_dim)
nn_input_dim = 2
nn_hdim = 3
w = np.random.randn(nn_input_dim,nn_hdim) / sqrt(nn_input_dim+nn_hdim)
nn_input_dim = 2
nn_hdim = 3
w = np.random.randn(nn_input_dim,nn_hdim) / sqrt(2.0/nn_input_dim)

3. 偏置項的初始化

通常偏置項(bias)初始化為0:

nn_input_dim = 2
nn_hdim = 3
b1 = np.zeros((1, nn_hdim))

對於Relu啟用神經元來說,可以將偏置項初始化為一個小的常數,比如0.01,但不確定這樣做是否提高收斂的表現,在實際應用中,也常初始化為0。