深度学习中的batch理解(batch size 一次喂给神经网络的数据大小量)
本文引用自:訓練神經(jīng)網(wǎng)絡時如何確定batch size?
文章目錄
- 前言
- 回顧
- Batch Size
- Which one?
前言
當我們要訓練一個已經(jīng)寫好的神經(jīng)網(wǎng)絡時,我們就要直面諸多的超參數(shù)了。這些超參數(shù)一旦選不好,那么很有可能讓神經(jīng)網(wǎng)絡跑的還不如感知機。因此在面對神經(jīng)網(wǎng)絡這種容量很大的model前,是很有必要深刻的理解一下各個超參數(shù)的意義及其對model的影響的。
回顧
簡單回顧一下神經(jīng)網(wǎng)絡的一次迭代過程:
即,首先選擇n個樣本組成一個batch,然后將batch丟進神經(jīng)網(wǎng)絡,得到輸出結果。再將輸出結果與樣本label丟給loss函數(shù)算出本輪的loss,而后就可以愉快的跑BP算法了(從后往前逐層計算參數(shù)之于loss的導數(shù))。最后將每個參數(shù)的導數(shù)配合步長參數(shù)來進行參數(shù)更新。這就是訓練過程的一次迭代。
Batch Size
由此,最直觀的超參數(shù)就是batch的大小——我們可以一次性將整個數(shù)據(jù)集喂給神經(jīng)網(wǎng)絡,讓神經(jīng)網(wǎng)絡利用全部樣本來計算迭代時的梯度(即傳統(tǒng)的梯度下降法),也可以一次只喂一個樣本(即隨機梯度下降法,也稱在線梯度下降法),也可以取個折中的方案,即每次喂一部分樣本讓其完成本輪迭代(即batch梯度下降法)。
數(shù)學基礎不太好的初學者可能在這里犯迷糊——一次性喂500個樣本并迭代一次,跟一次喂1個樣本迭代500次相比,有區(qū)別嗎?
其實這兩個做法就相當于:
第一種:
total = 舊參下計算更新值1+舊參下計算更新值2+…+舊參下計算更新值500 ;
新參數(shù) = 舊參數(shù) + total
第二種:
新參數(shù)1 = 舊參數(shù) + 舊參數(shù)下計算更新值1;
新參數(shù)2 = 新參數(shù)1 + 新參數(shù)1下計算更新值1;
新參數(shù)3 = 新參數(shù)2 + 新參數(shù)2下計算更新值1;
…
新參數(shù)500 = 新參數(shù)500 + 新參數(shù)500下計算更新值1;
也就是說,第一種是將參數(shù)一次性更新500個樣本的量,第二種是迭代的更新500次參數(shù)。當然是不一樣的啦。
那么問題來了,哪個更好呢?
Which one?
我們首先分析最簡單的影響,哪種做法收斂更快呢?
我們假設每個樣本相對于大自然真實分布的標準差為σ,那么根據(jù)概率統(tǒng)計的知識,很容易推出n個樣本的標準差為 \sigma/\sqrt{n} (有疑問的同學快翻開概率統(tǒng)計的課本看一下推導過程)。從這里可以看出,我們使用樣本來估計梯度的時候,1個樣本帶來σ的標準差,但是使用n個樣本區(qū)估計梯度并不能讓標準差線性降低(也就是并不能讓誤差降低為原來的1/n,即無法達到σ/n),而n個樣本的計算量卻是線性的(每個樣本都要平等的跑一遍前向算法)。
由此看出,顯然在同等的計算量之下(一定的時間內(nèi)),使用整個樣本集的收斂速度要遠慢于使用少量樣本的情況。換句話說,要想收斂到同一個最優(yōu)點,使用整個樣本集時,雖然迭代次數(shù)少,但是每次迭代的時間長,耗費的總時間是大于使用少量樣本多次迭代的情況的。
那么是不是樣本越少,收斂越快呢?
理論上確實是這樣的,使用單個單核cpu的情況下也確實是這樣的。但是我們要與工程實際相結合呀~實際上,工程上在使用GPU訓練時,跑一個樣本花的時間與跑幾十個樣本甚至幾百個樣本的時間是一樣的!當然得益于GPU里面超多的核,超強的并行計算能力啦。因此,在工程實際中,從收斂速度的角度來說,小批量的樣本集是最優(yōu)的,也就是我們所說的mini-batch。這時的batch size往往從幾十到幾百不等,但一般不會超過幾千(你有土豪顯卡的話,當我沒說)。
那么,如果我真有一個怪獸級顯卡,使得一次計算10000個樣本跟計算1個樣本的時間相同的話,是不是設置10000就一定是最好的呢?雖然從收斂速度上來說是的,但!是!
我們知道,神經(jīng)網(wǎng)絡是個復雜的model,它的損失函數(shù)也不是省油的燈,在實際問題中,神經(jīng)網(wǎng)絡的loss曲面(以model參數(shù)為自變量,以loss值為因變量畫出來的曲面)往往是非凸的,這意味著很可能有多個局部最優(yōu)點,而且很可能有鞍點!
插播一下,鞍點就是loss曲面中像馬鞍一樣形狀的地方的中心點,如下圖:
(圖片來自《Deep Learning》)
想象一下,在鞍點處,橫著看的話,鞍點就是個極小值點,但是豎著看的話,鞍點就是極大值點(線性代數(shù)和最優(yōu)化算法過關的同學應該能反應過來,鞍點處的Hessian矩陣的特征值有正有負。不理解也沒關系,小夕過幾天就開始寫最優(yōu)化的文章啦~),因此鞍點容易給優(yōu)化算法一個“我已經(jīng)收斂了”的假象,殊不知其旁邊有一個可以跳下去的萬丈深淵。。。(可怕)
回到主線上來,小夕在《機器學習入門指導(4)》中提到過,傳統(tǒng)的最優(yōu)化算法是無法自動的避開局部最優(yōu)點的,對于鞍點也是理論上很頭疼的東西。但是實際上,工程中卻不怎么容易陷入很差勁的局部最優(yōu)點或者鞍點,這是為什么呢?
暫且不說一些很高深的理論如“神經(jīng)網(wǎng)絡的loss曲面中的局部最優(yōu)點與全局最優(yōu)點差不太多”,我們就從最簡單的角度想~
想一想,樣本量少的時候會帶來很大的方差,而這個大方差恰好會導致我們在梯度下降到很差的局部最優(yōu)點(只是微微凸下去的最優(yōu)點)和鞍點的時候不穩(wěn)定,一不小心就因為一個大噪聲的到來導致炸出了局部最優(yōu)點,或者炸下了馬(此處請保持純潔的心態(tài)!),從而有機會去尋找更優(yōu)的最優(yōu)點。
因此,與之相反的,當樣本量很多時,方差很小(咦?最開始的時候好像在說標準差來著,反正方差與標準差就差個根號,沒影響的哈~),對梯度的估計要準確和穩(wěn)定的多,因此反而在差勁的局部最優(yōu)點和鞍點時反而容易自信的呆著不走了,從而導致神經(jīng)網(wǎng)絡收斂到很差的點上,跟出了bug一樣的差勁。
小總結一下,batch的size設置的不能太大也不能太小,因此實際工程中最常用的就是mini-batch,一般size設置為幾十或者幾百。但是!
好像這篇文章的轉(zhuǎn)折有點多了誒。。。
細心的讀者可能注意到了,這之前我們的討論是基于梯度下降的,而且默認是一階的(即沒有利用二階導數(shù)信息,僅僅使用一階導數(shù)去優(yōu)化)。因此對于SGD(隨機梯度下降)及其改良的一階優(yōu)化算法如Adagrad、Adam等是沒問題的,但是對于強大的二階優(yōu)化算法如共軛梯度法、L-BFGS來說,如果估計不好一階導數(shù),那么對二階導數(shù)的估計會有更大的誤差,這對于這些算法來說是致命的。
因此,對于二階優(yōu)化算法,減小batch換來的收斂速度提升遠不如引入大量噪聲導致的性能下降,因此在使用二階優(yōu)化算法時,往往要采用大batch哦。此時往往batch設置成幾千甚至一兩萬才能發(fā)揮出最佳性能。
另外,聽說GPU對2的冪次的batch可以發(fā)揮更佳的性能,因此設置成16、32、64、128…時往往要比設置為整10、整100的倍數(shù)時表現(xiàn)更優(yōu)(不過我沒有驗證過,有興趣的同學可以試驗一下~
總結
以上是生活随笔為你收集整理的深度学习中的batch理解(batch size 一次喂给神经网络的数据大小量)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python 从字符串中提取数字 re.
- 下一篇: 深度学习中batch_size、epoc