深度機器學習中的batch的大小對學習效果有何影響?
如題,在深度學習中,剛入門的小弟一直聽聞一個batch中同時訓練多個數據可以得到較好的效果,於是小弟在caffe上跑deepID的網路時對如何選取batchsize頗具困惑。懇求萬能的知友給予指點~~
談談深度學習中的 Batch_Size
Batch_Size(批尺寸)是機器學習中一個重要參數,涉及諸多矛盾,下面逐一展開。
首先,為什麼需要有 Batch_Size 這個參數?
Batch 的選擇,首先決定的是下降的方向。如果數據集比較小,完全可以採用全數據集 ( Full Batch Learning )的形式,這樣做至少有 2 個好處:其一,由全數據集確定的方向能夠更好地代表樣本總體,從而更準確地朝向極值所在的方向。其二,由於不同權重的梯度值差別巨大,因此選取一個全局的學習率很困難。 Full Batch Learning 可以使用Rprop 只基於梯度符號並且針對性單獨更新各權值。
對於更大的數據集,以上 2 個好處又變成了 2 個壞處:其一,隨著數據集的海量增長和內存限制,一次性載入所有的數據進來變得越來越不可行。其二,以 Rprop 的方式迭代,會由於各個 Batch 之間的採樣差異性,各次梯度修正值相互抵消,無法修正。這才有了後來 RMSProp 的妥協方案。
既然 Full Batch Learning 並不適用大數據集,那麼走向另一個極端怎麼樣?
所謂另一個極端,就是每次只訓練一個樣本,即 Batch_Size = 1。這就是在線學習(Online Learning)。線性神經元在均方誤差代價函數的錯誤面是一個拋物面,橫截面是橢圓。對於多層神經元、非線性網路,在局部依然近似是拋物面。使用在線學習,每次修正方向以各自樣本的梯度方向修正,橫衝直撞各自為政,難以達到收斂。
可不可以選擇一個適中的 Batch_Size 值呢?
當然可以,這就是批梯度下降法(Mini-batches Learning)。因為如果數據集足夠充分,那麼用一半(甚至少得多)的數據訓練算出來的梯度與用全部數據訓練出來的梯度是幾乎一樣的。
- 內存利用率提高了,大矩陣乘法的並行化效率提高。
- 跑完一次 epoch(全數據集)所需的迭代次數減少,對於相同數據量的處理速度進一步加快。
- 在一定範圍內,一般來說 Batch_Size 越大,其確定的下降方向越准,引起訓練震蕩越小。
盲目增大 Batch_Size 有何壞處?
- 內存利用率提高了,但是內存容量可能撐不住了。
- 跑完一次 epoch(全數據集)所需的迭代次數減少,要想達到相同的精度,其所花費的時間大大增加了,從而對參數的修正也就顯得更加緩慢。
- Batch_Size 增大到一定程度,其確定的下降方向已經基本不再變化。
調節 Batch_Size 對訓練效果影響到底如何?
這裡跑一個 LeNet 在 MNIST 數據集上的效果。MNIST 是一個手寫體標準庫,我使用的是 Theano 框架。這是一個 Python 的深度學習庫。安裝方便(幾行命令而已),調試簡單(自帶 Profile),GPU / CPU 通吃,官方教程相當完備,支持模塊十分豐富(除了 CNNs,更是支持 RBM / DBN / LSTM / RBM-RNN / SdA / MLPs)。在其上層有 Keras 封裝,支持 GRU / JZS1, JZS2, JZS3 等較新結構,支持 Adagrad / Adadelta / RMSprop / Adam 等優化演算法。
運行結果如上圖所示,其中絕對時間做了標幺化處理。運行結果與上文分析相印證:
- Batch_Size 太小,演算法在 200 epoches 內不收斂。
- 隨著 Batch_Size 增大,處理相同數據量的速度越快。
- 隨著 Batch_Size 增大,達到相同精度所需要的 epoch 數量越來越多。
- 由於上述兩種因素的矛盾, Batch_Size 增大到某個時候,達到時間上的最優。
- 由於最終收斂精度會陷入不同的局部極值,因此 Batch_Size 增大到某些時候,達到最終收斂精度上的最優。
歡迎一起討論。
批訓練的引入最大好處是針對非凸損失函數來做的, 畢竟非凸的情況下, 全樣本就算工程上算的動, 也會卡在局部優上, 批表示了全樣本的部分抽樣實現, 相當於人為引入修正梯度上的採樣雜訊,使「一路不通找別路」更有可能搜索最優值。
樓上很多說到隨機梯度收斂問題,物理上是這樣的理解,- 增加噪音擴大了你的行動範圍,不會受限於局部。
- 然而過大的行動範圍使得你的選擇過多而」迷茫「。
- 這是一個損失函數局部優有「多坑人」和局部優「數目太多好難選」之間的競爭,競爭平衡點才是你最終的訓練值。故此,最終的訓練值是一個分布,大夥們一般取平均來證明自己的模型多牛逼。
- 物理上,就是能量(坑好深)和熵(選擇多)的競爭結果,而且複雜系統中,能量和熵一輩子都在競爭,討論自由能最小值在非凸問題上的意義,比直接討論損失函數的最小值更有意義。
然而,這種牛逼,不僅依賴模型,而且依賴數據本身。調參需要預先建立競爭平衡的理論模型,單純用軟體刷指標只能用在某個數據集上,不具有轉移性。純浪費電!
這些觀點在大部分複雜物理系統的採樣,自旋玻璃的研究,蛋白質摺疊構象搜索上,都有廣泛的認識。但是工業界被凸優化影響過多了,除了特徵選擇和防止過擬合外可以通過直覺建立,遇到非凸優化問題,基本不可能拍腦袋調出一個通用的(如果數學上可以,物理上應該最先發現,然而並沒有)。於是,即便在物理上遇到這種問題,目前很low,而且節省成本的方法就是燒錢增加計算蠻力點。矛盾到我笑尿了。
caffe小菜鳥也來答一下,感覺就是大batch size在顯存能允許的情況下收斂速度是比較快的但有時的確會有陷入局部最小的情況,小batch size引入的隨機性會更大些,有時候能有更好的效果,但是就是收斂速度慢一些……
還有就是除了batch size這個參數外,如果在solver setting中有momentum這個參數的話也要注意batch size的選取,具體參考一下caffe的tutorial
關於訓練參數怎麼選取可以參考以下一些文章:
Bengio的 Practical recommendations for gradient-based learning
http://link.springer.com/chapter/10.1007/978-3-642-35289-8_26
Lecun 和 Bottou的 Efficient Backprop
http://link.springer.com/chapter/10.1007/978-3-642-35289-8_3
還有一個代碼上的細節,就是caffe的代碼實現上選取一個batch的時候似乎是按著資料庫的圖片順序選取輸入圖片的,所以在生成資料庫的時候切記要shuffle一下圖片順序~
供題主參考,求大神指正~
2017年6月3號 update:一年多之後忽然又想起了這個答案的存在,那我就多說幾句,隨著batch normalization的普及,收斂速度已經不像前bn時代一樣需要非常玄學的調參,現在一般都還是採取大batch size,畢竟GPU友好嘛,高票答案說的batch size大了一個epoch update數量少了的這個缺點在bn面前似乎也沒太多存在感了。不過bn的壞處就是不能用太小的batch size,要不然mean和variance就偏了。所以現在一般是顯存能放多少就放多少。而且實際調起模型來,真的是數據分布和預處理更為重要,數據不行的話 玩再多花招也沒用
ICLR 2017 有一篇論文專門討論了這個問題
On Large-Batch Training for Deep Learning: Generalization Gap and Sharp Minima(Nitish Shirish Keskar, Dheevatsa Mudigere, Jorge Nocedal, Mikhail Smelyanskiy, Ping Tak Peter Tang)
「We investigate the cause for this generalization drop in the large-batch regime and present numerical evidence that supports the view that large-batch methods tend to converge to sharp minimizers of the training and testing functions—and as is well known, sharp minima lead to poorer generalization. In contrast, small-batch methods consistently converge to flat minimizers, and our experiments support a commonly held view that this is due to the inherent noise in the gradient estimation」
太大的batch size 容易陷入sharp minima,泛化性不好
其實是有影響的。batch數太小,而類別又比較多的時候,真的可能會導致loss函數震蕩而不收斂,尤其是在你的網路比較複雜的時候。這個做過幾個實驗,但是沒有詳細的做,主要是針對googlenet,alexnet以及vgg幾個模型(實驗結果就是batch為32的時候,alex開始收斂,但是googlenet不收斂;提高batch size,googlenet開始收斂)。
就像lecun[note](http://cilvr.nyu.edu/lib/exe/fetch.php?media=deeplearning:dl-optimization.pdf)里說的一樣,隨機梯度下降不能像full batch那樣明顯的保證收斂。一般而言,根據你的GPU顯存,設置為最大,而且一般要求是8的倍數(比如32,128),這樣,GPU內部的並行運算效率最高。
那麼怎麼選擇batch number呢?就像剛才說的,8的倍數,然後是稍微大一點(一般而言)。另外一個方法,就是選擇一部分數據,跑幾個batch看看你的loss是不是在變小,選擇一個合適的就可以了。
看你GPU顯存,顯存大就把batch size設大點,反之亦然。一般情況下對學習效果沒影響。
補充點細節:
事實上從優化的角度來說最快的是純stochastic,即batch size為1。
關於這一點參見Leon Bottou的分析:http://leon.bottou.org/publications/pdf/compstat-2010.pdf。當然,文中的分析適用於large scale的情況下,但deep neural net適用的條件之一就是有大量數據。另外http://cilvr.nyu.edu/lib/exe/fetch.php?media=deeplearning:dl-optimization.pdf 的第11頁也有比較stochastic和batch的優劣。
拿Yann Lecun在上述第二個鏈接第10頁中舉的toy example來說,如果事實上只有100個數據點,但有人各複製了10遍拿給你,你不知道。這時候你如果做batch gradient descent,更只用了100個點效果一樣;而做stochastic gradient descent則相當於做了10個epoch。相近的計算量後者效果顯然更好。至於mini batch,要你取的每個mini batch都很diverse的情況才會效果好。
當然你會說,現實中哪會有100個數據各重複10遍就直接拿來用的?沒錯,是不會,但現實中的數據,尤其是large scale的數據中,必然有大量的redundancy,不然你也很難學出有較好泛化性的model。因此stochastic在large scale總是優於batch。
那為什麼還要用mini batch呢?這是由於GPU並行運算的性質,同時把多組數據傳過去一起運算比一條一條運算來的快,因而mini batch只是為了充分利用GPU memory而做出的妥協。既然如此,batch size也調到剛好能塞進顯存就差不多了。搞機器學習大忌就是不做實驗想當然,話說這種問題題主跑幾組不同的batch不就知道了...調參調參不調哪來的參~
另外,運用在不同的領域,不同的網路結構,不同的訓練方法,batch的取法,用法和影響也不一樣。不知道題主問的是哪種batch?可以考慮兩個極端:A.全部數據作為一個batch和 B.每個採樣作為一個batch
A.如果用全部數據作為一個batch,優點有如下:
1. 這樣理論上是可以得到全局收斂的
2. 可以用一些加速收斂演算法,比如L-BFGS之類的
3. 便於並行計算
但是同樣存在缺點:
如果數據集過大,訓練會很慢的
B.每個採樣作為一個batch,優點有如下
1. B方法在每個採樣上的參數修正方向會與整體最優的方向有出入。這條看似是個缺點,實際上,DNN因為是非線性模型,有很多參數,現有目標函數會有很多局部極值,這就會導致模型不精確。因為A方法每次修正依賴於現有模型和所有數據,很難跳出這些局部極值,所以A方法是一種很依賴於初始模型的方法。而B方法基於每個採樣去修正,修正幅度大了以後,就容易跳出這些局部極值,避免過擬合發生。B方法一般不依賴於初始模型,所以可以用來訓練初始的神經網路。之後再用A方法或者下面介紹的C方法優化
2. 速度在大部分情況比A方法快。
缺點就是
1. 難以並行計算
2. 因為每次更新基於單個採樣,很容易導致難以收斂。這個發生原因和優點1 是一樣的。這種現象有時是優點有時也是缺點,主要取決於學習率的選擇。
於是就有第三種情況,C:一部分數據作為一個batch,這種情況每次更新模型修正幅度沒有A那麼小,也沒有B那麼大,而且可以並行計算,所以速度也比較快。
一般用的時候,在非監督訓練階段,可以先用B方法創建初始模型,
然後在監督訓練階段,選擇小batch size進行初步訓練,讓模型跳出局部極值,之後用大的batch size讓模型收斂,這樣一般能達到比較好的效果
簡而言之,步子太大容易扯著蛋...
我也看到過說理論上batchsize=1是最好的,不過實際上調的時候,可能因為我調參的能力比較有限,確實batchsize太小會出現網路收斂不穩定,最後結果比較差的情況,這個在ImageNet和其他資料庫上都遇到過,而batchsize太大確實也會影響隨機性的引入。目前一般調ImageNet的時候,大家都喜歡把顯存佔滿,不過小一些的庫,個人感覺還是應該大大小小都嘗試一下。不知道各路大神有沒有什麼好辦法指點一下。。
深度神經網路的優化是個nonconvex problem.所以基於SGD的訓練batch size不能取過大。過大的batchsize的結果是網路很容易收斂到一些不好的局部最優點。。同樣太小的batch也存在一些問題,比如訓練速度很慢,訓練不容易收斂等。。具體的batch size的選取和訓練集的樣本數目相關。。舉個例子,比如在3小時的語音識別庫(大約108萬個樣本)訓練DNN,通常batch 取128..而在300小時的庫上會取1024..
batch_size設的大一些,收斂得快,也就是需要訓練的次數少,準確率上升得也很穩定,但是實際使用起來精度不高。
batch_size設的小一些,收斂得慢,而且可能準確率來回震蕩,所以還要把基礎學習速率降低一些;但是實際使用起來精度較高。
一般我只嘗試batch_size=64或者batch_size=1兩種情況。
我自己寫的CNN 網路 按照在線學習的方式 ,對每個樣本計算完就更新一次權重,不知道為啥,我的網路不收斂,然後輸出層各節點值趨于越趨於一致。
先看看caffe中各個model設置的大小再想想
我的batch_size,設置為1,(共55類)accuracy增長了很大,搞不懂什麼情況。
推薦閱讀:
※機器學習,在理論和編程方面要如何準備?
※分布的相似度(距離)用什麼模型比較好?
※怎樣進行大數據的入門級學習?
※看技術書, 數學公式推導需要會計算么?
※計算機視覺方向博士如何做好科研?
TAG:機器學習 | 深度學習(Deep Learning) |