另外添加了50層的ResNet進行fine-tuning,結果得到了進一步的提高,超越了SVM在這一數據集上的最佳performance(87%)
---------------------------------------------------------------------------------------------------------------------------
Deep Learning或者說CNN在圖像識別這一領域取得了巨大的進步,那麼自然我們就想將CNN應用到我們自己的數據集上,但這時通常就會面臨一個問題:通常我們的dataset都不會特別大,一般不會超過1萬張,甚至更少,每一類圖片只有幾十或者十幾張。這時候,直接應用這些數據訓練一個網絡的想法就不可行了,因爲深度學習成功的一個關鍵性因素就是大量帶標籤數據組成的訓練集。如果只利用手頭上這點數據,即使我們利用非常好的網絡結構,也達不到很高的performance。這時候,fine-tuning的思想就可以很好解決我們的問題:我們通過對ImageNet上訓練出來的模型(如CaffeNet,VGGNet,ResNet)進行微調,然後應用到我們自己的數據集上。
由於ImageNet數以百萬計帶標籤的訓練集數據,使得如CaffeNet之類的預訓練的模型具有非常強大的泛化能力,這些預訓練的模型的中間層包含非常多一般性的視覺元素,我們只需要對他的後幾層進行微調,在應用到我們的數據上,通常就可以得到非常好的結果。最重要的是,在目標任務上達到很高performance所需要的數據的量相對很少
這是Caffe官方提供的fine-tuing示例:Caffe | Fine-tuning for style recognition
下面我們看另外一個有趣的例子:
Oxford flowers分類
CaffeNet fine-tuned for Oxford flowers dataset
我修改了他們的一些代碼,使用了VGG_16而不是VGG_S模型,得到了更好的結果。
這是一個給花分類的例子,我們首先
git clone https://github.com/fish145/fine-tuning
cd Oxford102
克隆整個項目到本地,然後使用
python bootstrap.py
準備圖片,並下載CaffeNet和VGG-16這兩個預訓練模型
運行結束之後我們就可以看到這些美麗的圖片了
可以看到,總共8189張圖片被劃分爲訓練集(1020張),驗證集(1020張)和測試集(6149張)
1.微調CaffeNet
我們首先微調CaffeNet:
1).CaffeNet包含五層卷積層和三層全連接層,我們保留前面七層的參數,修改最後一層fc8爲fc8_oxford_102,將最後預測種類設置爲102,相當於我們只需要着重訓練這一層的參數,而微調前面的七層
看一下配置文件中值得注意的地方:
這是輸入部分,我們這裏使用ImageData的形式作爲Input,train.txt和valid.txt就是上面程序生成的數據列表,沒有使用以往常用的lmdb格式。因爲作爲微調,數據量相對很少,所以使用這種比較慢的形式也是可以接受的
2).然後設置base_lr爲0.001(原始模型中爲0.01),因爲我們只需要微調前面幾層的結構,而將最後一層的learning_rate設置爲0.01,來加快這一層的學習;如果你想完全停止除fc8_flickr外其他層的微調,你可以設置那些層的lr_mult爲0
看一下solver.prototxt:
可以看到除了base_lr和stepsize被修改外,其餘參數都基本一致
新加入的fc8_oxford_102層的learning_rate是前七層的十倍
3).stepsize也需要設置的小一點
接下來開始訓練,採用標準的訓練過程,用驗證集來調整參數,用測試集來測試最終的模型
caffe train -solver=solver.prototxt -weights=pretrained-weights.caffemodel -gpu 0
用以上命令進行訓練:
單GPU上訓練50000次用了六個小時左右,但其實三萬次的模型在測試集上的performance最高,後面應該出現了點過擬合,我們看一下訓練過程中的accuracy曲線圖
loss下降的非常快,大致30000次迭代之後,已經達到最佳
接下來我們在測試集(6149張)圖片上測試我們的模型:
caffe test -model=test.prototxt -weights=snapshot.caffemodel -iterations=123 -gpu 0
最後的accuracy爲81.43%,在驗證集上的accuracy爲84%左右,可以看出模型泛化能力還是非常好的
最後我們用訓練出來的模型對自己的圖片進行預測:
python predict.py test1.jpg deploy.prototxt pretrained.caffemodel ilsvrc_2012_mean.npy 227
參數依次是測試的圖片,配置文件,model,均值文件以及crop之後的圖片size
title爲花的種類以及爲該種類的概率。
如果有數量龐大的花的數據以及一些額外工作,我們就可以得到一個識花的工具了!
--------------------------------------------------------------------------------------------------------------------
嘗試將前五層的卷積層的lr調成0,只訓練全連接層,在驗證集上的結果如下圖:
82.85%,和之前的結果(83.95%)相比只下降了1%,再看一下測試集上:
也只下降了1%左右,但是訓練時間並沒有差多少,也是6個小時左右,所以用CaffeNet進行fine-tuning的話,這種策略並沒有什麼收益!
2.微調VGGNet(16 layers)
VGG_16包含13個卷積層和3個全連接層,和上面一樣,我們只修改最後一層,具體的結構大家參考項目下的配置文件即可
由於這個結構比較龐大,單GPU(Tesla K80)訓練大概需要兩天時間~
30000次迭代後,accuracy達到了89.1%,比CaffeNet結構提高了接近6%!如果使用現在最好的ResNet結構,應該可以達到90%以上的accuracy
下面比較一下二者的訓練曲線:
然後看一下在測試集上的表現:
在測試集上的accuracy爲86.3%,同樣是一個飛躍!這一結果已經無限逼近這個數據集上目前的最佳結果了(87%,使用SVM方法)
最後測試自己的圖片就不進行了,感興趣的可以自行嘗試,這個model比前一個的識別能力要更好
---------------------------------------------------------------------------------------------------------------------------
嘗試將前十三層的卷積層的lr調成0,只訓練後三層全連接層,結果如下:
accuracy降到81.56%了,在測試集上更是連80%也沒有:
但是訓練時間降低到了16個小時,整整快了兩倍左右,但是對performance影響太大,所以也不推薦使用;
在層數較深的情況下,由於DL本身的特性,在越高層形成的特徵越抽象,而前面的卷積層則是顏色和邊緣這些比較泛化的特徵,所以在fine-tuning時,可以將前幾層conv層的lr置爲0,但是後面的conv不建議這麼做,否則對performance影響太大,得不償失!
---------------------------------------------------------------------------------------------------------------------------
3.微調ResNet(50 layers)
最近使用fine-tuning完成了一個task,爲達到最好的performance,使用了50層的ResNet結構。中間也遇到一些坑,一起寫在這裏,給大家一個借鑑。
1)數據轉換
由於50層的結構太深了,所以我們需要將數據轉換成lmdb格式,否則訓練起來太慢了,這裏使用caffe提供的convert_imageset.ex。
convert_imageset.exe --shuffle --resize_height=256 --resize_width=256 <root>/ train.txt oxford102_train_lmdb
--shuffle代表打亂數據順序,--resize代表將圖片resize至指定尺寸,<root>/爲圖片所在的根目錄,然後是文件集和生成的lmdb數據庫名,我們將train,test和valid均轉換成lmdb文件
2)生成配置文件
Kaiming大神給我們提供了他們訓練出來的模型:OneDrive
也有deploy.prototxt,可以參考deploy用一個script來生成。關於model,值得一提的是,官方的model只有conv1有bias_term,後面的那些卷積層均沒有偏置項,所以在生成prototxt時,需要把那些層的bias_term禁用。(這個地方,當時被坑了很久,後來找了很長時間,終於找到了這個bug)
3)訓練
使用了兩塊K80的GPU來進行訓練,一是爲了縮短訓練時間,二則一塊GPU沒有那麼大的顯存。最終只花了16個小時就迭代了5萬次,也可以看出LMDB數據庫的高效性!
再驗證集上達到了91.37%的Accuracy.
再來看一下測試集上的表現:
達到了88.08%的準確率,超過了目前在這一數據集上表現最好的SVM方法(87%)
ResNet果然沒有讓人失望!
總結
通過Caffe官方提供的fine-tuning和本文中給出的示例,可以看出,對於很多CV任務,我們不需要重新建模並訓練,可以在ILSVRC大賽中尋找類似的比較好的結果,然後下載預訓練的模型,根據我們的任務來微調模型即可。尤其是當我們的數據相對較少時,就更適合選擇這種辦法。既可以有效利用深度神經網絡強大的泛化能力,又可以免去設計複雜的模型以及耗時良久的訓練。目前最強大的模型是ResNet,很多視覺任務都可以通過fine-tuning ResNet得到非常好的performance!
這裏推廣一個好用的工具:微軟識花,是身邊一個非常厲害的小夥伴做的,基於260萬張花的鑑定照片,得到的可以一鍵識別400種花卉的工具,不過目前只支持ios