在訓練cnn網路的時候,常常會使用dropout來使得模型具有更好的泛化性,並防止過擬合。而dropout的實質則是以一定概率使得輸入網路的資料某些維度上變為0,這樣可以使得模型訓練更加有效。但是我們需要注意dropout層在訓練和測試的時候,模型架構是不同的。為什麼會產生這種差別呢?
標準的網路連線如下圖:
增加了dropout層的網路結構如下圖:
此處的$r_j^$是服從引數為p的伯努利分布的隨機數(0或者1),用一句話來說就是y這個向量的每乙個維度都會以概率p變為0。
問題來了,在訓練的時候我們是有dropout層的,那我們測試的時候還需要麼?答案是不需要dropout層了,而是直接把y輸入進網路。這時候問題又來了,如果直接把y輸入進網路,在訓練的時候y由於經歷了dropout層,意味著y的資料分布的期望應該是會乘以p的(舉個例子如果y的每乙個維度都是1,那麼經過dropout層之後,有些維度變成了0,那此時真正進入網路的數值分布其期望應該是p),而測試時沒有經過dropout層那就意味著訓練時輸入和測試時輸入的期望是不同的,那這個訓練好的權重將無法達到最優秀的狀態。那該如何處理才能保證這個期望的一致性呢?答案就是在測試時,將網路的權重全部乘以p。如下圖:
這就是含有dropout層的訓練與測試不同的地方。
前文講了dropout訓練和測試時的不同,接下來我們講講如何在pytorch建模時使用這個層。
pytorch實現dropout的方式主要有兩個,第乙個是f.dropout(out, p=0.5),第二個是nn.dropout(p=0.5),這兩者的區別其實就是f和nn的區別。第乙個是乙個函式,第二個是乙個nn.model類。那在實際使用中我們該使用什麼呢?在構建網路時我們該使用第二個,因為前面說到了dropout在訓練和測試時是不同的,因此我們的測試時使用model.eval()時,如果只使用的是f.dropout(out, p=0.5)那麼不會有變化,但是nn.dropout(p=0.5)已經被模型註冊成了nn.model類,因此此時會改變權重。
如果非要使用f.dropout(out, p=0.5),那可以增加乙個引數,根據文件顯示:
也就是out = nn.functional.dropout(out, p=0.5, training=self.training)。
class mynet(nn.module):def __init__(self, input_size, num_classes):
super(mynet, self).__init__()
self.fc1 = nn.linear(input_size, num_classes) # 輸入層到輸出層
self.dropout = nn.dropout(p=0.5) # dropout訓練
def forward(self, x):
out = self.dropout(x)
print('dropout層的輸出:', out)
out = self.fc1(out)
return out
input_size = 10
num_classes = 5
model = mynet(input_size, num_classes)
x = torch.arange(0,10).reshape(-1).float()print('輸入向量', x)
model.train()
print("訓練模式下:", model(x))
model.eval()
print("測試模式下:", model(x))
出現問題了,畫紅框部分應該是訓練模式下dropout層的輸出,確實有些維度變成了0,但是怎麼會出現8,10,仔細一看可以發現,dropout在遮蔽一些維度的數值同時,會將沒有遮蔽的數值進行調整(縮放)乘以$\frac$,此處的p=0.5,因此代入公式可以知道,沒有倍遮蔽的數值應該會被乘以2。這是為什麼呢?前文提到了dropout由於會改變輸入資料的均值,所以需要對權重進行改變,其實話有一種方式,在遮蔽一些數值的時候同時對其他沒有遮蔽的數值進行縮放使其的縮放後的均值依然保持原來均值,這樣在測試的時候就不用調整權重了。這就是nn.dropout的方式(其實f.dropout也是進行了這個樣的rescaled)。
理解dropout_張雨石的部落格-csdn部落格_dropout
dropout — pytorch 1.11.0 documentation
torch.nn.functional.dropout — pytorch 1.11.0 documentation
container of 的的的原理
另外一篇,同樣精彩,揭開linux核心中container of的神秘面紗 華清遠見嵌入式學院講師。在linux 核心中有乙個大名鼎鼎的巨集container of 這個巨集是用來幹嘛的呢?我們先來看看它在核心中是怎樣定義的。呵呵,乍一看不知道是什麼東東。我們先來分析一下container of p...
存在的就是合理的,發生的即是必然的。
筆者有時候會想,什麼是對,什麼是錯?對於追求某一件事情之前首先會考慮,為什麼我要做這件事情。所以經過自我分析和生活周邊環境的總結。我認為,對於乙個人來,這是在站在個體的角度上說。什麼是對的?就是你自己覺得是對的,它就是對的。不過這個只是你自己的想法。主觀上的正確,不代表客觀上也受到了別人的認可。就拿...
Apache的rewrite的重寫相關的引數
apache mod rewrite規則重寫的標誌一覽 使用mod rewrite時常用的伺服器變數 rewriterule規則表示式的說明 匹配任何單字元 chars 匹配字串 chars chars 不匹配字串 chars text1 text2 可選擇的字串 text1或text2 匹配0到1...