本文小編為大家詳細介紹“Pytorch中的model.train()和model.eval()怎么使用”,內容詳細,步驟清晰,細節處理妥當,希望這篇“Pytorch中的model.train()和model.eval()怎么使用”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。
pytorch可以給我們提供兩種方式來切換訓練和評估(推斷)的模式,分別是:model.train()
和 model.eval()
。
一般用法是:在訓練開始之前寫上 model.trian() ,在測試時寫上 model.eval() 。
在使用 pytorch 構建神經網絡的時候,訓練過程中會在程序上方添加一句model.train(),作用是 啟用 batch normalization 和 dropout 。
如果模型中有BN層(Batch Normalization)和 Dropout ,需要在 訓練時 添加 model.train()。
model.train() 是保證 BN 層能夠用到 每一批數據 的均值和方差。對于 Dropout,model.train() 是 隨機取一部分 網絡連接來訓練更新參數。
model.eval()的作用是 不啟用 Batch Normalization 和 Dropout。
如果模型中有 BN 層(Batch Normalization)和 Dropout,在 測試時 添加 model.eval()。
model.eval() 是保證 BN 層能夠用 全部訓練數據 的均值和方差,即測試過程中要保證 BN 層的均值和方差不變。對于 Dropout,model.eval() 是利用到了 所有 網絡連接,即不進行隨機舍棄神經元。
為什么測試時要用 model.eval() ?
訓練完 train 樣本后,生成的模型 model 要用來測試樣本了。在 model(test) 之前,需要加上model.eval(),否則的話,有輸入數據,即使不訓練,它也會改變權值。這是 model 中含有 BN 層和 Dropout 所帶來的的性質。
eval() 時,pytorch 會自動把 BN 和 DropOut 固定住,不會取平均,而是用訓練好的值。
不然的話,一旦 test 的 batch_size 過小,很容易就會被 BN 層導致生成圖片顏色失真極大。
eval() 在非訓練的時候是需要加的,沒有這句代碼,一些網絡層的值會發生變動,不會固定,你神經網絡每一次生成的結果也是不固定的,生成質量可能好也可能不好。
也就是說,測試過程中使用model.eval(),這時神經網絡會 沿用 batch normalization 的值,而并 不使用 dropout。
如果模型中有 BN 層(Batch Normalization)和 Dropout,需要在訓練時添加 model.train(),在測試時添加 model.eval()。
其中 model.train() 是保證 BN 層用每一批數據的均值和方差,而 model.eval() 是保證 BN 用全部訓練數據的均值和方差;
而對于 Dropout,model.train() 是隨機取一部分網絡連接來訓練更新參數,而 model.eval() 是利用到了所有網絡連接。
dropout 常常用于抑制過擬合。
設置Dropout時,torch.nn.Dropout(0.5),這里的 0.5 是指該層(layer)的神經元在每次迭代訓練時會隨機有 50% 的可能性被丟棄(失活),不參與訓練。也就是將上一層數據減少一半傳播。
前言:最近在把兩個模型的代碼整合到一起,發現有一個模型的代碼整合后性能大不如前,但基本上是源碼遷移,找了一天原因才發現是因為model.eval()和model.train()放錯了位置?。?!故在此介紹一下pytroch框架下model.train()、model.eval()的作用和不同點。
簡單的說:
model.train
放在網絡訓練前,model.eval
放在網絡測試前。
常見的位置擺放錯誤(也是我犯的錯誤)有把model.train()
放在for epoch in range(epoch):
前面,同時在test或者val(測試或者評估函數)中只放置model.eval
,這就導致了只有第一個epoch模型訓練是使用了model.train()
,之后的epoch模型訓練時都采用model.eval()
.可能會影響訓練好模型的性能。
修改方式:可以在test函數里return前面添加model.train()
或者把model.train()
放到for epoch in range(epoch):
語句下面。
model.train() for epoch in range(epoch): for train_batch in train_loader: ... zhibiao = test(epoch, test_loader, model) def test(epoch, test_loader, model): model.eval() for test_batch in test_loader: ... return zhibiao
model.train()和model.eval()的區別主要在于Batch Normalization和Dropout兩層。
如果模型中有BN層(Batch Normalization)和Dropout,在測試時添加model.eval()。model.eval()是保證BN層能夠用全部訓練數據的均值和方差,即測試過程中要保證BN層的均值和方差不變。對于Dropout,model.eval()是利用到了所有網絡連接,即不進行隨機舍棄神經元。
下面是model.train 和model.eval的源碼,可以看到是利用self.training = mode
來判斷是使用train還是eval。這個參數將傳遞到一些常用層,比如dropout、BN層等。
def train(self: T, mode: bool = True) -> T: r"""Sets the module in training mode. This has any effect only on certain modules. See documentations of particular modules for details of their behaviors in training/evaluation mode, if they are affected, e.g. :class:`Dropout`, :class:`BatchNorm`, etc. Args: mode (bool): whether to set training mode (``True``) or evaluation mode (``False``). Default: ``True``. Returns: Module: self """ self.training = mode for module in self.children(): module.train(mode) return self def eval(self: T) -> T: r"""Sets the module in evaluation mode. This has any effect only on certain modules. See documentations of particular modules for details of their behaviors in training/evaluation mode, if they are affected, e.g. :class:`Dropout`, :class:`BatchNorm`, etc. This is equivalent with :meth:`self.train(False) <torch.nn.Module.train>`. Returns: Module: self """ return self.train(False)
拿dropout層的源碼舉例,可以看到傳遞了self.training這個參數。
class Dropout(_DropoutNd): r"""During training, randomly zeroes some of the elements of the input tensor with probability :attr:`p` using samples from a Bernoulli distribution. Each channel will be zeroed out independently on every forward call. This has proven to be an effective technique for regularization and preventing the co-adaptation of neurons as described in the paper `Improving neural networks by preventing co-adaptation of feature detectors`_ . Furthermore, the outputs are scaled by a factor of :math:`\frac{1}{1-p}` during training. This means that during evaluation the module simply computes an identity function. Args: p: probability of an element to be zeroed. Default: 0.5 inplace: If set to ``True``, will do this operation in-place. Default: ``False`` Shape: - Input: :math:`(*)`. Input can be of any shape - Output: :math:`(*)`. Output is of the same shape as input Examples:: >>> m = nn.Dropout(p=0.2) >>> input = torch.randn(20, 16) >>> output = m(input) .. _Improving neural networks by preventing co-adaptation of feature detectors: https://arxiv.org/abs/1207.0580 """ def forward(self, input: Tensor) -> Tensor: return F.dropout(input, self.p, self.training, self.inplace)
在BN層中,主要涉及到四個需要更新的參數,分別是running_mean,running_var,weight,bias。這里的weight,bias是Pytorch官方實現中的叫法,有點誤導人,其實weight就是gamma,bias就是beta。當然它這樣的叫法也符合實際的應用場景。其實gamma,beta就是對規范化后的值進行一個加權求和操作running_mean,running_var是當前所求得的所有batch_size下的均值和方差,每經過一個mini_batch我們都會更新running_mean,running_var.為什么要更新它?因為測試的時候,往往是一個一個的圖像feed至網絡的,如果你在這里對其進行計算均值方差顯然是不合理的,所以model.eval()這個語句就是控制BN層中的running_mean,running_std不更新。采用訓練結束后的running_mean,running_std來規范化該張圖像。
dropout層在訓練過程中會隨機舍棄一些神經元用來提高性能,但測試過程中如果還是測試的模型還是和訓練時一樣隨機舍棄了一些神經元(不是原模型)這就和測試的本意相違背。因為測試的模型應該是我們最終得到的模型,而這個模型應該是一個完整的模型。
既然都講到這了,不了解一些BN層和dropout層的作用就說不過去了。
BN層的原理和作用建議讀一下這篇博客:神經網絡中BN層的原理與作用
dropout是指在深度學習網絡的訓練過程中,對于神經網絡單元,按照一定的概率將其暫時從網絡中丟棄。注意是暫時,對于隨機梯度下降來說,由于是隨機丟棄,故而每一個mini-batch都在訓練不同的網絡。
大規模的神經網絡有兩個缺點:費時、容易過擬合
Dropout的出現很好的可以解決這個問題,每次做完dropout,相當于從原始的網絡中找到一個更瘦的網絡。因而,對于一個有N個節點的神經網絡,有了dropout后,就可以看做是2^n個模型的集合了,但此時要訓練的參數數目卻是不變的,這就解決了費時的問題。
將dropout比作是有性繁殖,將基因隨機進行拆分,可以將優秀的基因傳下來,并且降低基因之間的聯合適應性,使得復雜的大段大段基因聯合適應性變成比較小的一個一個小段基因的聯合適應性。
dropout也能達到同樣的效果,它強迫一個神經單元,和隨機挑選出來的其他神經單元共同工作,達到好的效果。消除減弱了神經元節點間的聯合適應性,增強了泛化能力。
讀到這里,這篇“Pytorch中的model.train()和model.eval()怎么使用”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。