最近在跑一些網絡時發現,訓練完的網絡在測試集上的效果總是會受Batch_Size 大小的影響。這種現象跟以往自己所想象的有些出入,於是出於好奇,各種搜博客,大致得出了自己想要的答案,現寫一篇博客記錄一下。
在訓練過程中,一般有三種方式來從數據集中抽取數據,更新參數。一種是取所有的樣本算出梯度(Full Batch Learning),另一種是每次迭代只取一個樣本進行更新,也即在線學習(Online Learning),取Batch_Size = 1,還有一種是批梯度下降法(Mini-batches Learning)。對於取全數據集的方式來說,其確定的梯度下降方式代表樣本總體,因此能最准確地朝着極值方向更新。但由於深度學習常用的數據集往往是海量的,所以采用全數據集下降的方式通常難以實現。而在線學習的方式則是每次訓練只取一個樣本,這樣的訓練方式往往會導致梯度更新的方向不那么准確。而批梯度下降就是前面所述兩種方法的折中的方式,即每次迭代取一部分樣本進行更新。我們下面討論的就是使用批梯度下降方法設置Batch_size的情況。
那么Batch_Size究竟取多少最好呢?首先來說說Batch_Size對收斂速度的影響。一般來說,增大Batch_Size,所帶來的訓練時的標准差並不是線性增長的,比如訓練一個樣本的標准差為σ,那么取Batch_Size=n所帶來的標准差為σ/√n,而非σ/n。因此,如果采用多個訓練樣本來算梯度的話,其計算量是線性增長的,但標准差並不能線性降低。所以Batch_Size越大,其收斂所需的迭代次數會減少,但每次迭代的計算時間也會增多,總體來看的話,耗費的總時間反而比使用少量樣本來訓練要多。但是,由於我們跑網絡的時候可以用GPU並行計算,所以在一定范圍內增大Batch_size,跑一次iteration的時間其實是差不多的,因此適當增加Batch_size大小,能讓網絡更快收斂。
但是也不是說Batch_size越大越好,我們知道網絡最終收斂的時候並不總是在絕對最小值區域,很多時候是陷入了局部最小值,特別是我們常說的“鞍部”。這時候,如果Batch_size調得較小的話,其每次迭代下降的方向並不是最准確的,loss是在小范圍內震盪下降的,這反而有利於跳出局部最小值,從而尋找下一個loss更低的區域。還有一種說法,何凱明大神的論文Rethinking ImageNet pre-training也提到過,如果你的網絡中使用了BN層的話,而BN層的計算在batch size較小時受batch size參數影響較大,batch size越小,參數的統計信息越不可靠,也會影響最終的效果。因此調小Batch_size可以有效防止陷入局部最小值,但是由於BN層的存在也會影響最終的效果,同時Batch_size調得過小也容易導致網絡不收斂。所以在實際跑代碼的過程中你就會發現,對於某些任務比如圖像分割,調Batch_size是個很玄學的過程。。。
參考博客:
