權重初始化
模型權重的初始化對於網絡的訓練很重要, 不好的初始化參數會導致梯度傳播問題, 降低訓練速度; 而好的初始化參數, 能夠加速收斂, 並且更可能找到較優解. 如果權重一開始很小,信號到達最后也會很小;如果權重一開始很大,信號到達最后也會很大。不合適的權重初始化會使得隱藏層的輸入的方差過大,從而在經過sigmoid這種非線性層時離中心較遠(導數接近0),因此過早地出現梯度消失.如使用均值0,標准差為1的正態分布初始化在隱藏層的方差仍會很大. 不初始化為0的原因是若初始化為0,所有的神經元節點開始做的都是同樣的計算,最終同層的每個神經元得到相同的參數.
好的初始化方法通常只是為了增快學習的速度(加速收斂),在某些網絡結構中甚至能夠提高准確率.
下面介紹幾種權重初始化方式.
- 初始化為
小的隨機數
,如均值為0,方差為0.01的高斯分布:
W=0.01 * np.random.randn(D,H)
然而只適用於小型網絡,對於深層次網絡,權重小導致反向傳播計算中梯度也小,梯度"信號"被削弱. - 上面1中的分布的方差隨着輸入數量的增大而增大,可以通過正則化方差來提高權重收斂速率,初始權重的方式為正態分布:
w = np.random.randn(n) / sqrt(n)
. 這會使得中間結果\(z=\sum_i w_ix_i+b\)的方差較小,神經元不會飽和,學習速度不會減慢.
論文 Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification by He et al. 中闡述了ReLU神經元的權值初始化方式,方差為2.0/n, 高斯分布權重初始化為:w = np.random.randn(n) * sqrt(2.0/n)
, 這是使用ReLU的網絡所推薦的一種方式.
論文[Bengio and Glorot 2010]: Understanding the difficulty of training deep feedforward neuralnetworks 中推薦使用 \(\text{Var}(W) = \frac{2}{n_\text{in} + n_\text{out}}\). - Xavier (均勻分布)
- MSRA
上述初始化方式的1,2僅考慮每層輸入的方差, 而后兩種方式考慮輸入與輸出的方差, 保持每層的輸入與輸出方差相等. 2,4 方法中針對ReLU激活函數, 放大了一倍的方差.
Xavier權重初始化
Xavier初始化可以幫助減少梯度彌散問題, 使得信號在神經網絡中可以傳遞得更深。是最為常用的神經網絡權重初始化方法。
算法根據輸入和輸出神經元的數量自動決定初始化的范圍: 定義參數所在的層的輸入維度為n,輸出維度為m,那么參數將從\([-{\sqrt{6\over m+n}},{\sqrt{6\over m+n}}]\)均勻分布中采樣。
公式推導
假設輸入一層X,輸出一層Y,那么
按照獨立變量相乘的方差公式,可以計算出:
我們期望輸入X和權重W都是零均值,因此簡化為
進一步假設所有的\(X_i,W_i\)都是獨立同分布,則有:
即輸出的方差與輸入有關,為使輸出的方差與輸入相同,意味着使\(n\text{Var}(W_i)=1\).因此\(\text{Var}(W_i) = \frac{1}{n}=\frac{1}{n_{in}}\).
如果對反向傳播的梯度運用同樣的步驟,可得:\(\text{Var}(W_i) = \frac{1}{n_\text{out}}\).
由於\(n_{in},n_{out}\)通常不相等,所以這兩個方差無法同時滿足,作為一種折中的方案,可使用介於\(\frac{1}{n_{in}},\frac{1}{n_{out}}\)之間的數來代替:簡單的選擇是\(\text{Var}(W_i) = \frac{2}{n_\text{in} + n_\text{out}}\).
可以根據均勻分布的方差,反推出W的均勻分布:
由於 [a,b] 區間的均勻分布的方差為:\(\text{Var}={(b-a)^2\over 12}\),使其零均值,則b=-a,所以\(\text{Var}={(2b)^2\over 12}=\frac{2}{n_\text{in} + n_\text{out}}\),可得\(b={\sqrt{6}\over \sqrt{n_{in}+n_{out}}}\).
因此,Xavier初始化的就是按照下面的均勻分布(uniform distribution):
xavier權重初始化的作用,使得信號在經過多層神經元后保持在合理的范圍(不至於太小或太大)。
caffe當前的xavier實現代碼:
/* 輸入blob的shape:(num, a, b, c)對應(輸出channel,輸入channel,b*c=kernel size)
扇入 fan_in = a * b * c
扇出 fan_out = num * b * c
scale = sqrt(3 / n) 這里的n根據參數決定:fan_in, fan_out, 或着平均。
這里的sqrt(3 / n)中當n=(n_j + n_{j+1})/2時就是上面式子中的$\sqrt{6}/\sqrt{n_j + n_{j+1}}.
然后用[-scale,scale]的均勻分布隨機采樣初始化權重
*/
template <typename Dtype>
class XavierFiller : public Filler<Dtype> {
public:
explicit XavierFiller(const FillerParameter& param)
: Filler<Dtype>(param) {}
virtual void Fill(Blob<Dtype>* blob) {
int fan_in = blob->count() / blob->num();
int fan_out = blob->count() / blob->channels();
Dtype n = fan_in;
if (this->filler_param_.variance_norm() ==
FillerParameter_VarianceNorm_AVERAGE) {
n = (fan_in + fan_out) / Dtype(2);
} else if (this->filler_param_.variance_norm() ==
FillerParameter_VarianceNorm_FAN_OUT) {
n = fan_out;
}
Dtype scale = sqrt(Dtype(3) / n);
caffe_rng_uniform<Dtype>(blob->count(), -scale, scale,
blob->mutable_cpu_data());
}
};
MSRA Filler
上邊所提的初始化方式為使每層方差一致,從而不會發生前向傳播爆炸和反向傳播梯度消失等問題。對於ReLU激活函數,其使一半數據變成0,初始時這一半的梯度為0,而tanh和sigmoid等的輸出初始時梯度接近於1.因此使用ReLU的網絡的參數方差可能會波動。論文Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification,Kaiming He中提出使用\(\text{Var}(W) = \frac{2}{n_\text{in}}\)放大一倍方差來保持方差的平穩。
前向和后向推導的方差均控制在\({2\over n}\),綜合起來使用均值為0,方差為\(\sqrt{4\over n_{in}+n_{out}}\)的高斯分布.
caffe MSRA Filler實現代碼:
/**
* Fills a Blob with values $ x \sim N(0, \sigma^2) $
* A Filler based on the paper [He, Zhang, Ren and Sun 2015]:
* Specifically accounts for ReLU nonlinearities.
*/
template <typename Dtype>
class MSRAFiller : public Filler<Dtype> {
public:
explicit MSRAFiller(const FillerParameter& param)
: Filler<Dtype>(param) {}
virtual void Fill(Blob<Dtype>* blob) {
CHECK(blob->count());
int fan_in = blob->count() / blob->num();
int fan_out = blob->count() / blob->channels();
Dtype n = fan_in; // default to fan_in
if (this->filler_param_.variance_norm() ==
FillerParameter_VarianceNorm_AVERAGE) {
n = (fan_in + fan_out) / Dtype(2);
} else if (this->filler_param_.variance_norm() ==
FillerParameter_VarianceNorm_FAN_OUT) {
n = fan_out;
}
Dtype std = sqrt(Dtype(2) / n);
caffe_rng_gaussian<Dtype>(blob->count(), Dtype(0), std,
blob->mutable_cpu_data());
CHECK_EQ(this->filler_param_.sparse(), -1)
<< "Sparsity not supported by this Filler.";
}
};
bias初始化
通常初始化為0(若初始化為0.01等值,可能並不能得到好的提升,反而可能下降)
Batch Normalization
在網絡中間層中使用 Batch Normalization 層一定程度上能夠減緩對較好的網絡參數初始化的依賴,使用方差較小的參數分布即可. 參考論文 Batch Normalization。
總結
- 當前的主流初始化方式 Xavier,MSRA 主要是為了保持每層的輸入與輸出方差相等, 而參數的分布采用均勻分布或高斯分布均可.
- 在廣泛采用 Batch Normalization 的情況下, 使用普通的小方差的高斯分布即可.
- 另外, 在遷移學習的情況下, 優先采用預訓練的模型進行參數初始化.
參考