1. 程式人生 > >Pytorch使用預訓練模型加速訓練的技巧

Pytorch使用預訓練模型加速訓練的技巧

當屬於預訓練模型屬於下面的情況的時候,可以採用這個加速的技巧:

固定前部分的層,只改變網路後面層的引數。

比如,使用vgg16的預訓練模型,固定特徵提取層,改變後面的全連線層。要注意的是,如果固定的是特徵提取層+一個全連線層,也可以使用這個技巧,只要固定的是前一部分。

具體的做法是:
 把所有的資料都輸入進去特徵層,把得到的輸出儲存成張量儲存在記憶體(如果太多還可以儲存在本地)中,無論有多少批次,前面的這個過程只進行一次。然後把這些作為訓練資料,相當於只訓練了mlp,隨著批次的增加,相對速度將會提高的很明顯。

這樣做也很好理解,因為前提是不改變卷積層的引數,所以一般的訓練過程中,n個epoch,對一張圖片來說就會在特徵層中傳播n次,由於卷積層引數不改變,所以得到的結果也是一樣的。

通過這樣的操作就消除了大量的計算冗餘,加速也是理所當然的。猜想,這樣不僅省去了feedforward,而且還會省去backforward,這樣說的理由是,雖然程式碼中不更新卷積層的引數,並且卷積層在網路的最前端,可能大家都會覺得不會有梯度的計算了,如果required_grad=false,那麼卻是是不用計算梯度的,但是因為網路自己可能並不知道卷積層前面沒有其他層了,所以誤差可能還是要計算的。如果不計算,原始碼就應該有對需要梯度的網路層位置的判斷。

進一步的,如果網路中有某些模組對於資料來說不會因為批次改變而發生變化,也可以進行訓練一次,多次使用的策略。
還沒有跑類似的程式碼,可能遇到的問題:

  1. 資料太多,所有資料的輸出儲存起來超過了記憶體。這個時候需要權衡一下從硬碟讀取張量快,還是提取特徵快。做一下折中。
  2. label資料對應問題。這個應該可以通過一些程式設計來實現:把每個圖片的特徵和label儲存在一個元組裡面等等。

參考書籍:《Deep Learning with Pytorch》112頁附近

https://www.bilibili.com/read/cv1374357