5.6 Dropout
上一節(jié)我們著重講了L2正則化,這一節(jié)介紹另一種防止過(guò)擬合的常用方法Dropout。
5.6.1 什么是Dropout
Dropout是一種常見(jiàn)的正則化技術(shù),用于減少神經(jīng)網(wǎng)絡(luò)中的過(guò)擬合。它是由 Geoffrey Hinton 和他的團(tuán)隊(duì)在 2012 年提出的,并在他們的論文 《Improving neural networks by preventing co-adaptation of feature detectors》 中進(jìn)行了描述。
其核心思想是在訓(xùn)練過(guò)程中隨機(jī)“刪除”(即將其權(quán)重設(shè)為零)一些神經(jīng)元,從而使模型不能完全依賴(lài)于某些特定的特征。這樣可以防止神經(jīng)網(wǎng)絡(luò)對(duì)訓(xùn)練集過(guò)于依賴(lài),從而使模型更加泛化,也就是更好地適用于新的、未見(jiàn)過(guò)的數(shù)據(jù)。
在訓(xùn)練期間隨機(jī)將輸入特征的一部分“刪除”,而在測(cè)試期間則使用全部特征。通常在測(cè)試期間會(huì)使用所有可用的信息來(lái)得到最好的結(jié)果。因此,在測(cè)試期間一般不使用 Dropout。
Dropout 在神經(jīng)網(wǎng)絡(luò)訓(xùn)練中取得了很大的成功,并且現(xiàn)在已經(jīng)成為了一種標(biāo)準(zhǔn)的正則化技術(shù)。它在解決過(guò)擬合問(wèn)題方面非常有效,因此經(jīng)常用于解決深度學(xué)習(xí)中的過(guò)擬合問(wèn)題。
5.6.2 Dropout的工作原理

如上圖所示,Dropout的工作流程主要可以分為以下幾步:

5.6.3 Dropout的代碼實(shí)現(xiàn)
為了更直觀的理解Dropout的作用,我們用一個(gè)例子演示在有無(wú)Dropout情況下,模型的效果對(duì)比。
首先導(dǎo)入相關(guān)庫(kù),定義超參數(shù)。然后生成兩組線性數(shù)據(jù)集,分別是訓(xùn)練集和測(cè)試集,并引入部分噪聲。
import?torch
import?torch.nn?as?nn
import?matplotlib.pyplot?as?plt
#?隨機(jī)數(shù)種子
torch.manual_seed(2333)
#?定義超參數(shù)
num_samples?=?20?#?樣本數(shù)
hidden_size?=?200?#?隱藏層大小
num_epochs?=?500??#?訓(xùn)練輪數(shù)
#?生成訓(xùn)練集和測(cè)試集
x_train?=?torch.unsqueeze(torch.linspace(-1,?1, num_samples),?1)
y_train?=?x_train?+?0.3?*?torch.randn(num_samples,?1)
x_test?=?torch.unsqueeze(torch.linspace(-1,?1, num_samples),?1)
y_test?=?x_test?+?0.3?*??torch.randn(num_samples,?1)
接下來(lái)定義兩個(gè)模型,一個(gè)是可能會(huì)過(guò)擬合的網(wǎng)絡(luò),其中包含3個(gè)隱藏層,激活函數(shù)使用ReLU函數(shù)。另一個(gè)網(wǎng)絡(luò)結(jié)構(gòu)一模一樣,區(qū)別在于加入了Dropout層,其中概率p設(shè)置為0.5。
#?定義一個(gè)可能會(huì)過(guò)擬合的網(wǎng)絡(luò)
net_overfitting?=?torch.nn.Sequential(
????torch.nn.Linear(1, hidden_size),
????torch.nn.ReLU(),
????torch.nn.Linear(hidden_size, hidden_size),
????torch.nn.ReLU(),
????torch.nn.Linear(hidden_size,?1),
)
#?定義一個(gè)包含?Dropout?的網(wǎng)絡(luò)
net_dropout?=?torch.nn.Sequential(
????torch.nn.Linear(1, hidden_size),
????torch.nn.Dropout(0.5), ?# p=0.5
????torch.nn.ReLU(),
????torch.nn.Linear(hidden_size, hidden_size),
????torch.nn.Dropout(0.5), ?# p=0.5
????torch.nn.ReLU(),
????torch.nn.Linear(hidden_size,?1),
)
接下來(lái),分別訓(xùn)練這兩個(gè)模型,這里使用均方誤差(MSE)作為損失函數(shù)。
#?定義優(yōu)化器和損失函數(shù)
optimizer_overfitting?=?torch.optim.Adam(net_overfitting.parameters(), lr=0.01)
optimizer_dropout?=?torch.optim.Adam(net_dropout.parameters(), lr=0.01)
criterion?=?nn.MSELoss()
#?訓(xùn)練網(wǎng)絡(luò)
for?i?in?range(num_epochs):
????pred_overfitting?=?net_overfitting(x_train)
????pred_dropout?=?net_dropout(x_train)
????
????loss_overfitting?=?criterion(pred_overfitting, y_train)
????loss_dropout?=?criterion(pred_dropout, y_train)
????optimizer_overfitting.zero_grad()
????optimizer_dropout.zero_grad()
????
????loss_overfitting.backward()
????loss_dropout.backward()
????
????optimizer_overfitting.step()
????optimizer_dropout.step()
最后,使用?Matplotlib 繪制訓(xùn)練集和測(cè)試集,以及兩個(gè)模型的擬合曲線。
#?在測(cè)試過(guò)程中不使用?Dropout
net_overfitting.eval()
net_dropout.eval()
#?預(yù)測(cè)
test_pred_overfitting?=?net_overfitting(x_test)
test_pred_dropout?=?net_dropout(x_test)
#?繪制擬合效果
plt.scatter(x_train.data.numpy(), y_train.data.numpy(), c='r', alpha=0.3, label='train')
plt.scatter(x_test.data.numpy(), y_test.data.numpy(), c='b', alpha=0.3, label='test')
plt.plot(x_test.data.numpy(), test_pred_overfitting.data.numpy(),?'r-', lw=2, label='overfitting')
plt.plot(x_test.data.numpy(), test_pred_dropout.data.numpy(),?'b--', lw=2, label='dropout')
plt.legend(loc='upper left')
plt.ylim((-2,?2))
plt.show()

在這個(gè)例子中,我們定義了兩個(gè)網(wǎng)絡(luò),一個(gè)是可能會(huì)產(chǎn)生過(guò)擬合現(xiàn)象的網(wǎng)絡(luò),另一個(gè)是一模一樣的結(jié)構(gòu),唯一的區(qū)別就是增加了Dropout層。然后分別進(jìn)行訓(xùn)練,用Matplotlib繪制出數(shù)據(jù)集和模型擬合的效果。從上圖中可以看到,第一個(gè)網(wǎng)絡(luò)在訓(xùn)練集上明顯產(chǎn)生了過(guò)擬合現(xiàn)象,而增加了Dropout層的網(wǎng)絡(luò)更為穩(wěn)定。由此可以看出,Dropout可以有效降低過(guò)擬合的風(fēng)險(xiǎn)。
5.6.4 Dropout的另一種理解

Dropout還可以被類(lèi)比成集成大量深層神經(jīng)網(wǎng)絡(luò)的一種Bagging方法。每做一次丟棄,相當(dāng)于從原始的網(wǎng)絡(luò)中采樣得到一個(gè)子網(wǎng)絡(luò),那么,最終的網(wǎng)絡(luò)可以近似看作集成了指數(shù)級(jí)個(gè)不同網(wǎng)絡(luò)的集成學(xué)習(xí)模型。
如上圖所示,Dropout訓(xùn)練是由所有子網(wǎng)絡(luò)組成的集合,其中子網(wǎng)絡(luò)通過(guò)從基本網(wǎng)絡(luò)中刪除一部分神經(jīng)元得到。我們從具有兩個(gè)可見(jiàn)單元和兩個(gè)隱藏單元的基本網(wǎng)絡(luò)開(kāi)始。這四個(gè)單元有十六個(gè)可能的子集。右圖展示了從原始網(wǎng)絡(luò)中丟棄不同的神經(jīng)元子集而形成的所有十六個(gè)子網(wǎng)絡(luò)。在這個(gè)小例子中,所得到的大部分網(wǎng)絡(luò)已經(jīng)失去從輸入連接到輸出的路徑。但當(dāng)層較寬時(shí),丟棄所有從輸入到輸出的可能路徑的概率變小,所以這個(gè)問(wèn)題不太可能出現(xiàn)在層較寬的網(wǎng)絡(luò)中。
5.6.5 Dropout的優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
可以有效地減少過(guò)擬合的風(fēng)險(xiǎn)。Dropout 在訓(xùn)練過(guò)程中隨機(jī)地清零一定比例的輸入特征,從而使得模型不能依賴(lài)于任何一個(gè)特定的輸入特征。這樣可以使得模型更加穩(wěn)健,并且在新的數(shù)據(jù)上的性能也更好。
Dropout 相對(duì)來(lái)說(shuō)比較簡(jiǎn)單,并且在實(shí)際應(yīng)用中也比較方便,適用于多種模型。
有研究顯示,Dropout相比其他計(jì)算開(kāi)銷(xiāo)小的正則化方法更有效。Dropout還可以與其他形式的正則化合并,得到進(jìn)一步的提升。
缺點(diǎn)
在訓(xùn)練過(guò)程中會(huì)降低訓(xùn)練效率。因?yàn)橐隓ropout之后相當(dāng)于每次只是訓(xùn)練的原先網(wǎng)絡(luò)的一個(gè)子網(wǎng)絡(luò),為了達(dá)到同樣的精度需要的訓(xùn)練次數(shù)會(huì)增多。
損失函數(shù)無(wú)法被明確定義。因?yàn)槊看蔚紩?huì)隨機(jī)消除一些神經(jīng)元的影響,因此無(wú)法確保損失函數(shù)單調(diào)遞減。
梗直哥提示:其實(shí)介紹了這么多概念,只要記得Dropout能夠有效降低過(guò)擬合的風(fēng)險(xiǎn),同時(shí)適用多種模型即可。如果你想了解更多內(nèi)容,歡迎入群學(xué)習(xí)(加V: gengzhige99)
更多視頻講解,歡迎點(diǎn)擊收看機(jī)器學(xué)習(xí)必修課
最新上線《深度學(xué)習(xí)必修課》帶你探索ChatGPT等前沿技術(shù)。
