DL開源框架Caffe | 模型微調 (finetune)的場景、問題、技巧以及解決方案


轉自:http://blog.csdn.net/u010402786/article/details/70141261

前言

什么是模型的微調?

   
  使用別人訓練好的網絡模型進行訓練,前提是必須和別人用同一個網絡,因為參數是根據網絡而來的。當然最后一層是可以修改的,因為我們的數據可能並沒有1000類,而只有幾類。把最后一層的輸出類別和層的名稱改一下就可以了。用別人的參數、修改后的網絡和自己的數據進行訓練,使得參數適應自己的數據,這樣一個過程,通常稱之為微調(fine tuning). 

微調時候網絡參數是否更新?

  
  更新,finetune的過程相當於繼續訓練,跟直接訓練的區別是初始化的時候: 
   a. 直接訓練是按照網絡定義指定的方式初始化(如高斯隨機初始化) 
  b. finetune是用你已經有的參數文件來初始化(就是之前訓練好的caffemodel)

 


**第一部分:Caffe命令行解析** —————

一、訓練模型代碼

  腳本:

./build/tools/caffe train -solver models/finetune/solver.prototxt -weights models/vgg_face_caffe/VGG_FACE.caffemodel -gpu 0

  BAT命令:  

..\..\bin\caffe.exe train --solver=.\solver.prototxt -weights .\test.caffemodel pause
二、caffe命令全解析

  http://www.cnblogs.com/denny402/p/5076285.html


第二部分:微調參數調整示例

一、各類模型finetune示例

Caffe finetune Resnet-50

http://blog.csdn.net/tangwenbo124/article/details/56070322

Caffe finetune googlenet

http://blog.csdn.net/sinat_30071459/article/details/51679995

Caffe finetune FCN

http://blog.csdn.net/zy3381/article/details/50458331

Caffe finetune Alexnet

                 這里寫圖片描述

二、參數調整注意
  • 首先修改名字,這樣預訓練模型賦值的時候這里就會因為名字不匹配從而重新訓練,也就達成了我們適應新任務的目的;
  • 調整學習速率,因為最后一層是重新學習,因此需要有更快的學習速率相比較其他層,因此我們將,weight和bias的學習速率加快10倍,目的是讓非微調層學習更快;
  • finetune時將最后的全連接層的名字全部修改,需要根據自己數據集的類別數重新設置fc8層的output數;
  • 數據集的類別號從0開始,中間要連續,否則會造成意外的錯誤
  • 數據集記得打亂,不然很可能不收斂;
  • 如果出現不收斂的問題,可以把solver里的lr設的小一點,一般從0.01開始,如果出現loss=nan了就不斷往小調整;
  • 可以把accuracy和loss的曲線畫出來,方便設定stepsize,一般在accuracy和loss都趨於平緩的時候就可以減小lr了;
  • finetune時應該用自己的數據集生成的均值文件(是否正確?);

第三部分:fine-tune的選擇經驗

  在fine-tune時,究竟該選擇哪種方式的Transfer Learning?需要考慮的因素有許多,其中最重要的兩條是新數據庫的規模和它與預訓練數據庫的相似程度,根據這兩條因素的不同配置,存在四種場景: 
   
  新數據庫小,和預訓練數據庫相似。因為數據庫比較小,fine-tune的話可能會產生過擬合,比較好的做法是用預訓練的網絡作為特征提取器,然后訓練線性分類器用在新的任務上。 
  新數據庫比較大,和預訓練數據庫相似。這種情況下,不用擔心過擬合,可以放心地微調整個網絡。 
  新數據庫小,和預訓練數據庫不相似。這時,既不能微調,用預訓練網絡去掉最后一層作為特征提取器也不合適,可行的方案是用預訓練網絡的前面幾層的激活值作為特征,然后訓練線性分類器。 
  新數據庫大,和預訓練數據庫不相似。這時可以從頭開始訓練,也可以在預訓練的基礎上進行微調。 
  這里寫圖片描述 
   
  綜述:做freeze操作時,通常還會根據數據集在不同情況進行有選擇的性的finetune。如small datasets時,可以freeze前面conv layer-> fc4086來提取cnn在imagenet上的多類泛化特征來輔助作為分類的feature,再對如這邊revise的fc-20->softmax進行training。以此類推,如果是medium datasets則freeze到一半的conv。個人理解這樣做的很大原因在於lower level layer具有更強泛化的basic feature,同時記得考量你的數據來選擇。


第四部分:如何針對上述不同的方式進行網絡參數固定

比如有4個全連接層A->B->C->D: 

  a. 你希望C層的參數不會改變,C前面的AB層的參數也不會改變,這種情況也就是D層的梯度不往前反向傳播到D層的輸入blob(也就是C層的輸出blob 沒有得到梯度),你可以通過設置D層的lr_mult: 0,layer的梯度就不會反向傳播啦,前面的所有layer的參數也就不會改變了。 
  b. 你希望C層的參數不會改變,但是C前面的AB層的參數會改變,這種情況,只是固定了C層的參數,C層得到的梯度依然會反向傳播給前面的B層。只需要將對應的參數blob的學習率調整為0: 
  在layer里面加上param { lr_mult: 0 }就可以了,比如全連接層里面:

layer {
    type: "InnerProduct" param { # 對應第1個參數blob的配置,也就是全連接層的參數矩陣的配置 lr_mult: 0 # 學習率為0,其他參數可以看caffe.proto里面的ParamSpec這個類型 } param { # 對應第2個參數blob的配置,也就是全連接層的偏置項的配置 lr_mult: 0 # 學習率為0 } }

第五部分:Caffe fine-tune常見問題

一、按照網上的教程微調alexnet,為什么loss一直是87.3365?

  解決辦法:檢查數據集的標簽是否是從0開始,base_lr調低了一個數量級,batch_size調高一倍。 
   
  出現的原因:87.3365是個很特殊的數字,NAN經過SoftmaxWithLoss就產生了這個數字,所以就是你的FC8輸出全是NAN; 
   
  具體分析: 
  http://blog.csdn.net/jkfdqjjy/article/details/52268565?locationNum=14

二、Loss下降了,但是准確率沒有明顯變化?

  解決辦法:訓練前首先shuffle,其次學習率是否合適。

三、Data augmentation 的技巧總結:

轉自小白在閉關 https://www.zhihu.com/question/35339639

圖像亮度、飽和度、對比度的變化; 
PCA Jittering 
Random resize 
Random crop 
Horizontal/vertical filp 
旋轉仿射變換 
加高斯噪聲、模糊處理 
Label shuffle:類別不平衡數據的擴增,參見海康威視ILSVRC2016的report

               這里寫圖片描述

四、如何通過loss曲線判斷網絡訓練的情況:

  單獨的 loss 曲線能提供的信息很少的,一般會結合測試機上的 accuracy 曲線來判斷是否過擬合; 
  關鍵是要看你在測試集上的acc如何; 
  如果你的 learning_rate_policy 是 step 或者其他變化類型的話, loss 曲線可以幫助你選擇一個比較合適的 stepsize;

 

五、finetune_net.bin不能用之后,用新的方法做finetune會出問題,怎么解決? 

   
  給最后那個InnerProduct層換個名字。

 


第六部分:參考資料

1.http://caffe.berkeleyvision.org/gathered/examples/finetune_flickr_style.html 
2.https://www.zhihu.com/question/54775243 
3.http://blog.csdn.net/u012526120/article/details/49496617 
4.https://zhidao.baidu.com/question/363059557656952932.html

Caffe調參

一般fine tuning的方式,都是把learning rate(solver.prototxt)調低(為原來的十分之一),之后把訓練模型的最后一層或者兩層的學習速率調大一點————這就相當於,把模型的前面那些層的學習調低,使得參數更新的慢一點以達到微調的目的。但有可能會導致整個收斂速度變慢,因此還需要增加最大迭代次數。
關於調參,個人感覺很多時候都是經驗,在這個情景下,增加一個模塊效果是好的,在另一個場景可能就是不好的。沒有一個很好的理論支持你,應該怎么調整。簡單來講就是修改學習速率、batchsize等參數。
需要調節的參數(solver.prototxt)主要包括:
base_lr:初始學習率,這個是非常重要的一個參數;momentum:一般設置為0.9,如果base_lr特別低的話也可以設置為0.99或0.999等 weight_decay:默認0.005,可以適當調整,類似於正則化項;
lr_policy:學習率變化策略,常見的有fixed(固定), inv,step等,詳細的說明見http://stackoverflow.com/questions/30033096/what-is-lr-policy-in-caffe
最后如果loss出現不收斂的情況,可以嘗試一下以下幾種方法:

  1. 調小solver里的初始學習率
  2. 數據量小的話,可以只對最后幾層的權重進行調整,前面權重保持不變,即把前面的學習率置為0,一定程度上限制了激活的大小,這樣就限制了某一過大的誤差的影響,這樣可以避免迭代方向出現過大的變化。
  3. 在GPU可承受的范圍內調大batch_size的大小(賈揚清的解釋:理論上batch小是不會影響收斂的。小batch主要的問題是在FC層的計算可能會不是很efficient,如果實在無計可施,可以試試 ;網上其他博主的解釋:batch比較小 ,導致樣本覆蓋面過低,產生了非常多的局部極小點,在步長和方向的共同作用下,導致數據產生了震盪,導致了不收斂 )

總而言之,一般策略是先試一試參數,把display設小一點,多看看結果,找到合適的參數,再整個跑。這里有幾篇關於調參的論文(),可以看一下,基於理解和有合理解釋的調參才不會變為無意義的工作。

http://bealin.github.io/2016/10/23/Caffe%E5%AD%A6%E4%B9%A0%E7%B3%BB%E5%88%97%E2%80%94%E2%80%943Fine-tuning%E5%BE%AE%E8%B0%83%E7%BD%91%E7%BB%9C/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM