Fine tuning 模型微調

在前面的介紹卷積神經網絡的時候,說到過PyTorch已經爲我們訓練好了一些經典的網絡模型,那麼這些預訓練好的模型,是爲了我們進行微調使用的。
1 什麼是微調

針對於某個任務,自己的訓練數據不多,那怎麼辦? 沒關係,我們先找到一個同類的別人訓練好的模型,把別人現成的訓練好了的模型拿過來,換成自己的數據,調整一下參數,再訓練一遍,這就是微調(fine-tune)。 PyTorch裏面提供的經典的網絡模型都是官方通過Imagenet的數據集與訓練好的數據,如果我們的數據訓練數據不夠,這些數據是可以作爲基礎模型來使用的。
爲什麼要微調


對於數據集本身很小(幾千張圖片)的情況,從頭開始訓練具有幾千萬參數的大型神經網絡是不現實的,因爲越大的模型對數據量的要求越大,過擬合無法避免。這時候如果還想用上大型神經網絡的超強特徵提取能力,只能靠微調已經訓練好的模型。
可以降低訓練成本:如果使用導出特徵向量的方法進行遷移學習,後期的訓練成本非常低,用 CPU 都完全無壓力,沒有深度學習機器也可以做。
前人花很大精力訓練出來的模型在大概率上會比你自己從零開始搭的模型要強悍,沒有必要重複造輪子。


遷移學習 Transfer Learning

總是有人把 遷移學習和神經網絡的訓練聯繫起來,這兩個概念剛開始是無關的。 遷移學習是機器學習的分支,現在之所以 遷移學習和神經網絡聯繫如此緊密,現在圖像識別這塊發展的太快效果也太好了,所以幾乎所有的遷移學習都是圖像識別方向的,所以大家看到的遷移學習基本上都是以神經網絡相關的計算機視覺爲主,本文中也會以這方面來舉例子

遷移學習初衷是節省人工標註樣本的時間,讓模型可以通過一個已有的標記數據的領域向未標記數據領域進行遷移從而訓練出適用於該領域的模型,直接對目標域從頭開始學習成本太高,我們故而轉向運用已有的相關知識來輔助儘快地學習新知識

舉一個簡單的例子就能很好的說明問題,我們學習編程的時候會學習什麼? 語法、特定語言的API、流程處理、面向對象,設計模式,等等

這裏面語法和API是每一個語言特有的,但是面向對象和設計模式可是通用的,我們學了JAVA,再去學C#,或者Python,面向對象和設計模式是不用去學的,因爲原理都是一樣的,甚至在學習C#的時候語法都可以少學很多,這就是遷移學習的概念,把統一的概念抽象出來,只學習不同的內容。

遷移學習按照學習方式可以分爲基於樣本的遷移,基於特徵的遷移,基於模型的遷移,以及基於關係的遷移,這裏就不詳細介紹了。
二者關係

其實 “Transfer Learning” 和 “Fine-tune” 並沒有嚴格的區分,含義可以相互交換,只不過後者似乎更常用於形容遷移學習的後期微調中。 我個人的理解,微調應該是遷移學習中的一部分。微調只能說是一個trick。
如何微調

對於不同的領域微調的方法也不一樣,比如語音識別領域一般微調前幾層,圖片識別問題微調後面幾層,這個原因我這裏也只能講個大概,具體還要大神來解釋:

對於圖片來說,我們CNN的前幾層學習到的都是低級的特徵,比如,點、線、面,這些低級的特徵對於任何圖片來說都是可以抽象出來的,所以我們將他作爲通用數據,只微調這些低級特徵組合起來的高級特徵即可,例如,這些點、線、面,組成的是園還是橢圓,還是正方形,這些代表的含義是我們需要後面訓練出來的。

對於語音來說,每個單詞表達的意思都是一樣的,只不過發音或者是單詞的拼寫不一樣,比如 蘋果,apple,apfel(德語),都表示的是同一個東西,只不過發音和單詞不一樣,但是他具體代表的含義是一樣的,就是高級特徵是相同的,所以我們只要微調低級的特徵就可以了。

下面只介紹下計算機視覺方向的微調,摘自 cs231

ConvNet as fixed feature extractor.: 其實這裏有兩種做法:
    使用最後一個fc layer之前的fc layer獲得的特徵,學習個線性分類器(比如SVM)
    重新訓練最後一個fc layer

Fine-tuning the ConvNet

固定前幾層的參數,只對最後幾層進行fine-tuning,

對於上面兩種方案有一些微調的小技巧,比如先計算出預訓練模型的卷積層對所有訓練和測試數據的特徵向量,然後拋開預訓練模型,只訓練自己定製的簡配版全連接網絡。 這個方式的一個好處就是節省計算資源,每次迭代都不會再去跑全部的數據,而只是跑一下簡配的全連接

Pretrained models

這個其實和第二種是一個意思,不過比較極端,使用整個pre-trained的model作爲初始化,然後fine-tuning整個網絡而不是某些層,但是這個的計算量是非常大的,就只相當於做了一個初始化。
注意事項


新數據集和原始數據集合類似,那麼直接可以微調一個最後的FC層或者重新指定一個新的分類器
新數據集比較小和原始數據集合差異性比較大,那麼可以使用從模型的中部開始訓練,只對最後幾層進行fine-tuning
新數據集比較小和原始數據集合差異性比較大,如果上面方法還是不行的化那麼最好是重新訓練,只將預訓練的模型作爲一個新模型初始化的數據
新數據集的大小一定要與原始數據集相同,比如CNN中輸入的圖片大小一定要相同,纔不會報錯
如果數據集大小不同的話,可以在最後的fc層之前添加捲積或者pool層,使得最後的輸出與fc層一致,但這樣會導致準確度大幅下降,所以不建議這樣做
對於不同的層可以設置不同的學習率,一般情況下建議,對於使用的原始數據做初始化的層設置的學習率要小於(一般可設置小於10倍)初始化的學習率,這樣保證對於已經初始化的數據不會扭曲的過快,而使用初始化學習率的新層可以快速的收斂。


https://github.com/zergtant/pytorch-handbook/blob/master/chapter4/4.1-fine-tuning.ipynb

發佈了208 篇原創文章 · 獲贊 24 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章