怎麼選取訓練神經網路時的Batch size?

batch_size的選擇和訓練數據規模、神經網路層數、單元數有什麼關係?謝謝!


謝邀。邀請我的一定是訂閱號的粉絲,2333。

這個問題我已經詳細寫過了,搬過來。

原鏈接:訓練神經網路時如何確定batch的大小?

前言

當我們要訓練一個已經寫好的神經網路時,我們就要直面諸多的超參數了。這些超參數一旦選不好,那麼很有可能讓神經網路跑的還不如感知機。因此在面對神經網路這種容量很大的model前,是很有必要深刻的理解一下各個超參數的意義及其對model的影響的。

回顧

簡單回顧一下神經網路的一次迭代過程:

即,首先選擇n個樣本組成一個batch,然後將batch丟進神經網路,得到輸出結果。再將輸出結果與樣本label丟給loss函數算出本輪的loss,而後就可以愉快的跑BP演算法了(從後往前逐層計算參數之於loss的導數)。最後將每個參數的導數配合步長參數來進行參數更新。這就是訓練過程的一次迭代。

Batch Size

由此,最直觀的超參數就是batch的大小——我們可以一次性將整個數據集餵給神經網路,讓神經網路利用全部樣本來計算迭代時的梯度(即傳統的梯度下降法),也可以一次只喂一個樣本(即隨機梯度下降法,也稱在線梯度下降法),也可以取個折中的方案,即每次喂一部分樣本讓其完成本輪迭代(即batch梯度下降法)。

數學基礎不太好的初學者可能在這裡犯迷糊——一次性喂500個樣本并迭代一次,跟一次喂1個樣本迭代500次相比,有區別嗎?

其實這兩個做法就相當於:

第一種:

total = 舊參下計算更新值1+舊參下計算更新值2+...+舊參下計算更新值500 ;

新參數 = 舊參數 + total

第二種:

新參數1 = 舊參數 + 舊參數下計算更新值1;

新參數2 = 新參數1 + 新參數1下計算更新值1;

新參數3 = 新參數2 + 新參數2下計算更新值1;

...

新參數500 = 新參數500 + 新參數500下計算更新值1;

也就是說,第一種是將參數一次性更新500個樣本的量,第二種是迭代的更新500次參數。當然是不一樣的啦。

那麼問題來了,哪個更好呢?

Which one?

我們首先分析最簡單的影響,哪種做法收斂更快呢?

我們假設每個樣本相對於大自然真實分布的標準差為σ,那麼根據概率統計的知識,很容易推出n個樣本的標準差為 sigma/sqrt{n} (有疑問的同學快翻開概率統計的課本看一下推導過程)。從這裡可以看出,我們使用樣本來估計梯度的時候,1個樣本帶來σ的標準差,但是使用n個樣本區估計梯度並不能讓標準差線性降低(也就是並不能讓誤差降低為原來的1/n,即無法達到σ/n),而n個樣本的計算量卻是線性的(每個樣本都要平等的跑一遍前向演算法)。

由此看出,顯然在同等的計算量之下(一定的時間內),使用整個樣本集的收斂速度要遠慢於使用少量樣本的情況。換句話說,要想收斂到同一個最優點,使用整個樣本集時,雖然迭代次數少,但是每次迭代的時間長,耗費的總時間是大於使用少量樣本多次迭代的情況的。

那麼是不是樣本越少,收斂越快呢?

理論上確實是這樣的,使用單個單核cpu的情況下也確實是這樣的。但是我們要與工程實際相結合呀~實際上,工程上在使用GPU訓練時,跑一個樣本花的時間與跑幾十個樣本甚至幾百個樣本的時間是一樣的!當然得益於GPU裡面超多的核,超強的並行計算能力啦。因此,在工程實際中,從收斂速度的角度來說,小批量的樣本集是最優的,也就是我們所說的mini-batch。這時的batch size往往從幾十到幾百不等,但一般不會超過幾千(你有土豪顯卡的話,當我沒說)。

那麼,如果我真有一個怪獸級顯卡,使得一次計算10000個樣本跟計算1個樣本的時間相同的話,是不是設置10000就一定是最好的呢?雖然從收斂速度上來說是的,但!是!

我們知道,神經網路是個複雜的model,它的損失函數也不是省油的燈,在實際問題中,神經網路的loss曲面(以model參數為自變數,以loss值為因變數畫出來的曲面)往往是非凸的,這意味著很可能有多個局部最優點,而且很可能有鞍點!

插播一下,鞍點就是loss曲面中像馬鞍一樣形狀的地方的中心點,如下圖:

(圖片來自《Deep Learning》)

想像一下,在鞍點處,橫著看的話,鞍點就是個極小值點,但是豎著看的話,鞍點就是極大值點(線性代數和最優化演算法過關的同學應該能反應過來,鞍點處的Hessian矩陣的特徵值有正有負。不理解也沒關係,小夕過幾天就開始寫最優化的文章啦~),因此鞍點容易給優化演算法一個「我已經收斂了」的假象,殊不知其旁邊有一個可以跳下去的萬丈深淵。。。(可怕)

回到主線上來,小夕在《機器學習入門指導(4)》中提到過,傳統的最優化演算法是無法自動的避開局部最優點的,對於鞍點也是理論上很頭疼的東西。但是實際上,工程中卻不怎麼容易陷入很差勁的局部最優點或者鞍點,這是為什麼呢?

暫且不說一些很高深的理論如「神經網路的loss曲面中的局部最優點與全局最優點差不太多」,我們就從最簡單的角度想~

想一想,樣本量少的時候會帶來很大的方差,而這個大方差恰好會導致我們在梯度下降到很差的局部最優點(只是微微凸下去的最優點)和鞍點的時候不穩定,一不小心就因為一個大雜訊的到來導致炸出了局部最優點,或者炸下了馬(此處請保持純潔的心態!),從而有機會去尋找更優的最優點。

因此,與之相反的,當樣本量很多時,方差很小(咦?最開始的時候好像在說標準差來著,反正方差與標準差就差個根號,沒影響的哈~),對梯度的估計要準確和穩定的多,因此反而在差勁的局部最優點和鞍點時反而容易自信的呆著不走了,從而導致神經網路收斂到很差的點上,跟出了bug一樣的差勁。

小總結一下,batch的size設置的不能太大也不能太小,因此實際工程中最常用的就是mini-batch,一般size設置為幾十或者幾百。但是!

好像這篇文章的轉折有點多了誒。。。

細心的讀者可能注意到了,這之前我們的討論是基於梯度下降的,而且默認是一階的(即沒有利用二階導數信息,僅僅使用一階導數去優化)。因此對於SGD(隨機梯度下降)及其改良的一階優化演算法如Adagrad、Adam等是沒問題的,但是對於強大的二階優化演算法如共軛梯度法、L-BFGS來說,如果估計不好一階導數,那麼對二階導數的估計會有更大的誤差,這對於這些演算法來說是致命的。

因此,對於二階優化演算法,減小batch換來的收斂速度提升遠不如引入大量雜訊導致的性能下降,因此在使用二階優化演算法時,往往要採用大batch哦。此時往往batch設置成幾千甚至一兩萬才能發揮出最佳性能。

另外,聽說GPU對2的冪次的batch可以發揮更佳的性能,因此設置成16、32、64、128...時往往要比設置為整10、整100的倍數時表現更優(不過我沒有驗證過,有興趣的同學可以試驗一下~


@夕小瑤 說的很具體了。

我來簡單說一下怎麼操作吧,

1. Batch size設置以餵飽你的硬體為主要標準。只要顯卡塞得下,首先挑大的。

2. 當感覺訓練時噪音不夠時,比如收斂碰到鞍點或者局部最小值時,調小batch size。(很少會碰到)

3. 當感覺訓練時噪音太大時,調大batch size到餵飽硬體(因為2很少碰到,這也很少做),再不行就調小learning rate,也可以直接調小learning rate。

綜合起來用就是常見的帶learning rate下降的sgd。開始時依賴batch帶來的噪音快速下降,接下來使用較低的learning rate消除這些噪音尋求穩定收斂。一般而言只要batch不太大,樣本里的噪音總是夠用的。

cpu是非常討厭16,32,64…… 這樣大小的數組的,gpu好像沒有類似的問題,但我還是要勸大家,超參的選取隨意點。

欠兩個引用,等下再補。

---- 補引用

https://danluu.com/3c-conflict/ 這個詳細說了CPU為什麼討厭16,32,知乎上也有個回答說到過,自己也碰到過,蠻常見的。當年在high performance computing的課上學的,當時gpu還不流行,有誰能告訴我gpu的情況嗎?謝謝啦。

http://www.jmlr.org/papers/volume13/bergstra12a/bergstra12a.pdf 告訴大家選超參要隨意點


batch size 不是永遠越大越好。

更大的 batch size 更能準確地計算出梯度,mini-batch 只是用更少的計算來近似梯度。直覺上好像更大的 batch 更好因為更「準確」。

實踐結果比較反直覺,因為深度模型的代價函數非常不平整,完整的梯度也只能往局部極小值跑,所以大 batch size 帶來的準確的梯度可能也沒什麼用。反而有時候小 batch size 帶來的雜訊可以更快的找到不錯的極小值。

但是,更大的 batch size 在並行計算上更佔優勢,太小的 batch-size 發揮不了 gpu 的性能。所以當我們覺得 batch 要更大,主要是為了更好的並行,而不是為了更精確的梯度。

在深度學習里好像追求精確意義不大,比如更高精度的浮點數並沒有什麼幫助,還不如減小精度來換取計算速度。比如調參時 ramdom search 居然不比 grid search 表現差,非常反直覺。

補充:

@dengdan在評論里指出,小batch訓練的穩定性較差。小batch確實有這個缺點,而且對設置學習速率有更高的要求,否則可能引起惡性的震蕩無法收斂。但是小batch的優點仍然是顯著的,DL書里建議使用逐步增加的batch size來兼并兩者的優點。


大batch size相當於小lr,反之亦然。可以根據收斂速度進行一定選擇。

另外如果用了batchnorm,batch size別太小(大於64?)

如果不用batchnorm,可以考慮用小batch size甚至1 來得到最優的結果。具體看deep learning那本書的相關段落(見下圖第一段),我自己做的實驗也可以驗證。


  1. full batch是特殊的mini batch。
  2. batch size越大每次迭代的梯度越接近樣本的真實梯度。
  3. 小的batch size能有效避免樣本中的冗餘信息。
  4. 大的batch能更充分利用GPU。
  5. batch的大小並沒有固定模式,不需要非要2^n的size。
  6. 綜合以上幾點進行權衡,選擇你的batch。


感覺不是樓上所說的那樣吧,越大越好吧。。。。

the noisiness is exactly what you want in non-convex optimization, because it helps you escape from saddle points or local minima

但是如果batch size=1,或者說batch size很小的話,比較容易震蕩導致不收斂,當然batch size不能一味增大,即使顯存夠了,原因就是上面所說的,稍微小點的mini batch能夠增加noise,能夠跳過局部最小


batch_size與模型本身沒有多大關係,除非模型中使用了batch_normalization或者其他與batch相關的運算。

如樓上所說,顯存允許時,batch_size越大越好,因為大batch_size下的梯度更穩定, 訓練更容易收斂。


越大越好取決於顯存


推薦閱讀:

模式識別、機器學習、神經網路、(泛函分析?)的學習順序
機器學習中梯度下降演算法公式是不是有問題?
梯度下降or擬牛頓法?
CNN卷積神經網路當前最主要的應用除了圖像處理還有其他的應用方面嗎?
多類分類下為什麼用softmax而不是用其他歸一化方法?

TAG:神經網路 | 深度學習DeepLearning | TensorFlow |