Dropout簡(jiǎn)單理解

前言

訓(xùn)練神經(jīng)網(wǎng)絡(luò)模型時(shí),如果訓(xùn)練樣本較少,為了防止模型過(guò)擬合,Dropout可以作為一種trikc供選擇。Dropout是hintion最近2年提出的,源于其文章Improving neural networks by preventing co-adaptation of feature detectors.中文大意為:通過(guò)阻止特征檢測(cè)器的共同作用來(lái)提高神經(jīng)網(wǎng)絡(luò)的性能。本篇博文就是按照這篇論文簡(jiǎn)單介紹下Dropout的思想,以及從用一個(gè)簡(jiǎn)單的例子來(lái)說(shuō)明該如何使用dropout。

基礎(chǔ)知識(shí):

Dropout是指在模型訓(xùn)練時(shí)隨機(jī)讓網(wǎng)絡(luò)某些隱含層節(jié)點(diǎn)的權(quán)重不工作,不工作的那些節(jié)點(diǎn)可以暫時(shí)認(rèn)為不是網(wǎng)絡(luò)結(jié)構(gòu)的一部分,但是它的權(quán)重得保留下來(lái)(只是暫時(shí)不更新而已),因?yàn)橄麓螛颖据斎霑r(shí)它可能又得工作了(有點(diǎn)抽象,具體實(shí)現(xiàn)看后面的實(shí)驗(yàn)部分)。

按照hinton的文章,他使用Dropout時(shí)訓(xùn)練階段和測(cè)試階段做了如下操作:

在樣本的訓(xùn)練階段,在沒(méi)有采用pre-training的網(wǎng)絡(luò)時(shí)(Dropout當(dāng)然可以結(jié)合pre-training一起使用),hintion并不是像通常那樣對(duì)權(quán)值采用L2范數(shù)懲罰,而是對(duì)每個(gè)隱含節(jié)點(diǎn)的權(quán)值L2范數(shù)設(shè)置一個(gè)上限bound,當(dāng)訓(xùn)練過(guò)程中如果該節(jié)點(diǎn)不滿足bound約束,則用該bound值對(duì)權(quán)值進(jìn)行一個(gè)規(guī)范化操作(即同時(shí)除以該L2范數(shù)值),說(shuō)是這樣可以讓權(quán)值更新初始的時(shí)候有個(gè)大的學(xué)習(xí)率供衰減,并且可以搜索更多的權(quán)值空間(沒(méi)理解)。

在模型的測(cè)試階段,使用”mean network(均值網(wǎng)絡(luò))”來(lái)得到隱含層的輸出,其實(shí)就是在網(wǎng)絡(luò)前向傳播到輸出層前時(shí)隱含層節(jié)點(diǎn)的輸出值都要減半(如果dropout的比例為50%),其理由文章說(shuō)了一些,可以去查看(沒(méi)理解)。

關(guān)于Dropout,文章中沒(méi)有給出任何數(shù)學(xué)解釋,Hintion的直觀解釋和理由如下:

1. 由于每次用輸入網(wǎng)絡(luò)的樣本進(jìn)行權(quán)值更新時(shí),隱含節(jié)點(diǎn)都是以一定概率隨機(jī)出現(xiàn),因此不能保證每2個(gè)隱含節(jié)點(diǎn)每次都同時(shí)出現(xiàn),這樣權(quán)值的更新不再依賴于有固定關(guān)系隱含節(jié)點(diǎn)的共同作用,阻止了某些特征僅僅在其它特定特征下才有效果的情況。

2. 可以將dropout看作是模型平均的一種。對(duì)于每次輸入到網(wǎng)絡(luò)中的樣本(可能是一個(gè)樣本,也可能是一個(gè)batch的樣本),其對(duì)應(yīng)的網(wǎng)絡(luò)結(jié)構(gòu)都是不同的,但所有的這些不同的網(wǎng)絡(luò)結(jié)構(gòu)又同時(shí)share隱含節(jié)點(diǎn)的權(quán)值。這樣不同的樣本就對(duì)應(yīng)不同的模型,是bagging的一種極端情況。個(gè)人感覺(jué)這個(gè)解釋稍微靠譜些,和bagging,boosting理論有點(diǎn)像,但又不完全相同。

3. native bayes是dropout的一個(gè)特例。Native bayes有個(gè)錯(cuò)誤的前提,即假設(shè)各個(gè)特征之間相互獨(dú)立,這樣在訓(xùn)練樣本比較少的情況下,單獨(dú)對(duì)每個(gè)特征進(jìn)行學(xué)習(xí),測(cè)試時(shí)將所有的特征都相乘,且在實(shí)際應(yīng)用時(shí)效果還不錯(cuò)。而Droput每次不是訓(xùn)練一個(gè)特征,而是一部分隱含層特征。

4. 還有一個(gè)比較有意思的解釋是,Dropout類(lèi)似于性別在生物進(jìn)化中的角色,物種為了使適應(yīng)不斷變化的環(huán)境,性別的出現(xiàn)有效的阻止了過(guò)擬合,即避免環(huán)境改變時(shí)物種可能面臨的滅亡。

文章最后當(dāng)然是show了一大把的實(shí)驗(yàn)來(lái)說(shuō)明dropout可以阻止過(guò)擬合。這些實(shí)驗(yàn)都是些常見(jiàn)的benchmark,比如Mnist, Timit, Reuters, CIFAR-10, ImageNet.

實(shí)驗(yàn)過(guò)程:

本文實(shí)驗(yàn)時(shí)用mnist庫(kù)進(jìn)行手寫(xiě)數(shù)字識(shí)別,訓(xùn)練樣本2000個(gè),測(cè)試樣本1000個(gè),用的是matlab的https://github.com/rasmusbergpalm/DeepLearnToolbox,代碼在test_example_NN.m上修改得到。關(guān)于該toolbox的介紹可以參考網(wǎng)友的博文【面向代碼】學(xué)習(xí) Deep Learning(一)Neural Network。這里我只用了個(gè)簡(jiǎn)單的單個(gè)隱含層神經(jīng)網(wǎng)絡(luò),隱含層節(jié)點(diǎn)的個(gè)數(shù)為100,所以輸入層-隱含層-輸出層節(jié)點(diǎn)依次為784-100-10. 為了使本例子簡(jiǎn)單話,沒(méi)用對(duì)權(quán)值w進(jìn)行規(guī)則化,采用mini-batch訓(xùn)練,每個(gè)mini-batch樣本大小為100,迭代20次。權(quán)值采用隨機(jī)初始化。

實(shí)驗(yàn)結(jié)果:

沒(méi)用Dropout時(shí):

訓(xùn)練樣本錯(cuò)誤率(均方誤差):0.032355

測(cè)試樣本錯(cuò)誤率:15.500%

使用Dropout時(shí):

訓(xùn)練樣本錯(cuò)誤率(均方誤差):0.075819

測(cè)試樣本錯(cuò)誤率:13.000%

可以看出使用Dropout后,雖然訓(xùn)練樣本的錯(cuò)誤率較高,但是訓(xùn)練樣本的錯(cuò)誤率降低了,說(shuō)明Dropout的泛化能力不錯(cuò),可以防止過(guò)擬合。

實(shí)驗(yàn)主要代碼及注釋:

test_dropout.m:

%% //導(dǎo)入minst數(shù)據(jù)并歸一化
load mnist_uint8;
train_x = double(train_x(1:2000,:)) / 255;
test_x = double(test_x(1:1000,:))  / 255;
train_y = double(train_y(1:2000,:));
test_y = double(test_y(1:1000,:)); % //normalize
[train_x, mu, sigma] = zscore(train_x);% //歸一化train_x,其中mu是個(gè)行向量,mu是個(gè)列向量
test_x = normalize(test_x, mu, sigma);% //在線測(cè)試時(shí),歸一化用的是訓(xùn)練樣本的均值和方差,需要特別注意

%% //without dropout
rng(0);
nn = nnsetup([784 100 10]);% //初步構(gòu)造了一個(gè)輸入-隱含-輸出層網(wǎng)絡(luò),其中包括了
                           % //權(quán)值的初始化,學(xué)習(xí)率,momentum,激發(fā)函數(shù)類(lèi)型,
                           % //懲罰系數(shù),dropout等
opts.numepochs =  20;   %  //Number of full sweeps through data
opts.batchsize = 100;  %  //Take a mean gradient step over this many samples
[nn, L] = nntrain(nn, train_x, train_y, opts);
[er, bad] = nntest(nn, test_x, test_y);
str = sprintf('testing error rate is: %f',er);
disp(str) %% //with dropout
rng(0);
nn = nnsetup([784 100 10]);
nn.dropoutFraction = 0.5;   %  //Dropout fraction,每一次mini-batch樣本輸入訓(xùn)練時(shí),隨機(jī)扔掉50%的隱含層節(jié)點(diǎn)
opts.numepochs =  20;        %  //Number of full sweeps through data
opts.batchsize = 100;       %  //Take a mean gradient step over this many samples
nn = nntrain(nn, train_x, train_y, opts);
[er, bad] = nntest(nn, test_x, test_y);
str = sprintf('testing error rate is: %f',er);
disp(str)</pre>

下面來(lái)分析與dropout相關(guān)的代碼,集中在上面test.m代碼的后面with drop部分。首先在訓(xùn)練過(guò)程中需要將神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)nn的dropoutFraction設(shè)置為一定比例,這里設(shè)置為50%:nn.dropoutFraction = 0.5;

然后進(jìn)入test_dropout.m中的nntrain()函數(shù),沒(méi)有發(fā)現(xiàn)與dropoutFraction相關(guān)的代碼,繼續(xù)進(jìn)入網(wǎng)絡(luò)前向傳播函數(shù)nnff()函數(shù)中,在網(wǎng)絡(luò)的隱含層節(jié)點(diǎn)激發(fā)函數(shù)值被計(jì)算出來(lái)后,有下面的代碼:

if(nn.dropoutFraction > 0) if(nn.testing)

                nn.a{i} = nn.a{i}.*(1 - nn.dropoutFraction); else nn.dropOutMask{i} = (rand(size(nn.a{i}))>nn.dropoutFraction);

                nn.a{i} = nn.a{i}.*nn.dropOutMask{i};

            end

        end</pre>

由上面的代碼可知,隱含層節(jié)點(diǎn)的輸出值以dropoutFraction百分比的幾率被隨機(jī)清0(注意此時(shí)是在訓(xùn)練階段,所以是else那部分的代碼),既然前向傳播時(shí)有些隱含節(jié)點(diǎn)值被清0了,那么在誤差方向傳播時(shí)也應(yīng)該有相應(yīng)的處理,果然,在反向傳播函數(shù)nnbp()中,有下面的代碼:

if(nn.dropoutFraction>0)

            d{i} = d{i} .* [ones(size(d{i},1),1) nn.dropOutMask{i}];

        end</pre>

也就是說(shuō)計(jì)算節(jié)點(diǎn)誤差那一項(xiàng)時(shí),其誤差項(xiàng)也應(yīng)該清0。從上面可以看出,使用dropout時(shí),其訓(xùn)練部分的代碼更改很少。

(有網(wǎng)友發(fā)私信說(shuō),反向傳播計(jì)算誤差項(xiàng)時(shí)可以不用乘以dropOutMask{i}矩陣,后面我仔細(xì)看了下bp的公式,一開(kāi)始也感覺(jué)不用乘有道理。因?yàn)樵创a中有為:

for i = 1 : (n - 1) if i+1==n
        nn.dW{i} = (d{i + 1}' * nn.a{i}) / size(d{i + 1}, 1);
    else nn.dW{i} = (d{i + 1}(:,2:end)' * nn.a{i}) / size(d{i + 1}, 1); 
    end
end</pre>

代碼進(jìn)行權(quán)重更新時(shí),由于需要乘以nn.a{i},而nn.a{i}在前向過(guò)程中如果被mask清掉的話(使用了dropout前提下),則已經(jīng)為0了。但其實(shí)這時(shí)錯(cuò)誤的,因?yàn)閷?duì)誤差敏感值作用的是與它相連接的前一層權(quán)值,并不是本層的權(quán)值,而本層的輸出a只對(duì)它的下一層權(quán)值更新有效。

再來(lái)看看測(cè)試部分,測(cè)試部分如hintion論文所說(shuō)的,采用mean network,也就是說(shuō)前向傳播時(shí)隱含層所有節(jié)點(diǎn)的輸出同時(shí)減小dropoutFraction百分比,即保留(1- dropoutFraction)百分比,代碼依舊是上面貼出的nnff()函數(shù)里滿足if(nn.testing)的部分:

if(nn.dropoutFraction > 0) if(nn.testing)

                nn.a{i} = nn.a{i}.*(1 - nn.dropoutFraction); else nn.dropOutMask{i} = (rand(size(nn.a{i}))>nn.dropoutFraction);

                nn.a{i} = nn.a{i}.*nn.dropOutMask{i};

            end

        end</pre>

上面只是個(gè)簡(jiǎn)單的droput實(shí)驗(yàn),可以用來(lái)幫助大家理解dropout的思想和使用步驟。其中網(wǎng)絡(luò)的參數(shù)都是采用toolbox默認(rèn)的,并沒(méi)有去調(diào)整它,如果該實(shí)驗(yàn)將訓(xùn)練樣本增大,比如6w張,則參數(shù)不變的情況下使用了dropout的識(shí)別率還有可能會(huì)降低(當(dāng)然這很有可能是其它參數(shù)沒(méi)調(diào)到最優(yōu),另一方面也說(shuō)明在樣本比較少的情況下,droput確實(shí)可以防止過(guò)擬合),為了體現(xiàn)droput的優(yōu)勢(shì),這里我只用了2000張訓(xùn)練樣本。

參考資料:

Hinton, G. E., et al. (2012). "Improving neural networks by preventing co-adaptation of feature detectors." arXiv preprint arXiv:1207.0580.

  [https://github.com/rasmusbergpalm/DeepLearnToolbox](https://github.com/rasmusbergpalm/DeepLearnToolbox)

 [【面向代碼】學(xué)習(xí) Deep Learning(一)Neural Network](http://blog.csdn.net/dark_scope/article/details/9421061)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容