1. 程式人生 > >caffe隨記(八)---使用caffe訓練FCN的pascalcontext-fcn32s模型(pascal-context資料集)

caffe隨記(八)---使用caffe訓練FCN的pascalcontext-fcn32s模型(pascal-context資料集)

本篇討論利用caffe進行FCN訓練(採用的是pascal-context資料集

1、下載FCN的框架

如圖是我在windows下的檢視
因為不同的資料來源和不同的FCN型別的網路結構並不同,對資料來源的讀取方式也不同,因此有很多分支,本篇博文以pascalcontext-fcn32s為例子講解fcn的訓練過程。
把上面的東西拷進伺服器,我是放在 ~/caffe/examples/ 目錄下的。資料夾命名為fcn.berkeleyvision.org
進行訓練之前要先保證caffe的安裝和編譯工作已經完成,且make和make pycaffe成功。

2、下載VOC2010資料集

原始資料集至少要包含以下兩個檔案:

解壓後得到一個資料夾VOCdevkit,放進伺服器。
我是放在 ~/caffe/data/pascalvoc/ 目錄下的。
輸入 
ln –s ~/caffe/data/pascalvoc/VOCdevkit/VOC2010   ~/caffe/examles/fcn.berkeleyvision.org/data/pascal/VOC2010
這是建立軟連線,至於為什麼到第9步就知道了,至於這個linux命令(ln)就自行百度吧

3、下載pascalcontext資料

下載如下幾個資料:

把這兩個壓縮包解壓後連同那個txt檔案一起拷入到伺服器中。 放在第一步中那個fcn.berkeleyvision.org資料夾下的data中的pascal-context資料夾中去,以我的路徑為例,就應該放入:
~/caffe/examples/ fcn.berkeleyvision.org/data/pascal-context



4、下載預訓練model


下載完成後更名為vgg16-fcn.caffemodel然後放入fcn.berkeleyvision.org資料夾中去,至於為什麼更名我待會兒會提到

5、新增python目錄

如果fcn.berkeleyvision.org不在python的搜尋目錄中,那麼就編輯 ~/.bashrc,增加以下一行內容到bashrc中去
export PYTHONPATH="你的路徑/fcn.berkeleyvision.org:$PYTHONPATH"
然後logout重新登入後生效

6、更改相關路徑

更改pascalcontext-fcn32s資料夾中的train.prototxt和val.prototxt裡的路徑,把param_str中的context_dir和voc_dir更改為自己的路徑

根據我們前面存放檔案的路徑,這裡只需要把../.../data/pascal-context改為../data/pascal-context,把../../data/pascal更改為../data/pascal,就是去掉前面一個../就行

7、建立目錄

在fcn.berkeleyvision.org/pascalcontext-fcn32s目錄下建立snapshot/train

8、更改層名

由於下載的vgg16layer.caffemodel中也有fc6,fc7和train.txt、val.txt中的fc6、fc7不一致,會導致錯誤, 所以我們把train.txt、val.txt中的所有fc6、fc7改成fc6x和fc7x,包括裡面的blob名,目的是不讓這個權重值傳過去。 如圖所示:
這是我擷取的訓練過程中的日誌,若你最後成功進行訓練了,就會打印出相關內容 (注意:這一步的設定其實是錯誤的,這是我第一次嘗試的步驟,正確的步驟請看文末我的分割線更新的內容)

9、更正solve.py

也在fcn.berkeleyvision.org目錄中有個solve.py,我們需要更改其中一些東西
首先在第一行假如以下內容:
import sys
然後它原來的weights是:
weights = '../ilsvrc-nets/vgg16-fcn.caffemodel'
這裡改一下路徑,改成:../vgg16-fcn.caffemodel(因為caffemodel我們就放在上一層的資料夾中的,這也是為什麼前面讓改名的原因,就是為了跟這裡一致) 然後我們第一步講到了一個建立軟連線的過程,你看一下sovle.py中有一行
這就是為什麼建立了一個軟連線的原因

10、重新編譯

需要把caffe目錄下的Makefile.config中的

WITH_PYTHON_LAYER=1

這句開啟,然後make clean

再 make all

再 make pycaffe

11、安裝python setproctitle包

如果系統缺少setproctitle。執行以下命令安裝:

pip install setproctitle

顯示以下內容說明安裝成功


12、開始訓練

在pascalcontest-fcn32s下,輸入以下命令開始訓練:

python solve.py

然後就會開始搭建layer然後各種資訊打印出來開始迭代,


--------------------------------------------------------------------------------------分割線---------------------------------------------------------------------------------------------

這個佔的記憶體有點大:我的情況如下:


佔了將近4個多G的記憶體

而且還很慢,跑了好幾個小時才跑到8000次, 而且8000次的時候出現了 Begin seg tests,然後就一直停在那裡一度不知道發生了什麼,如圖
最後等了好久才又有資訊顯示出來:
從時間上看,光是這裡就隔了將近一個小時吧,所以大家一定要有耐心,然後這裡顯示的準確度確實還不高 而且從開始算起已經跑了5個小時了才跑了將近9000次,離我們solver中規定的300000次還遠的不得了……所以等出結果了我再來更新博文吧

-------------------------------------------------------------------8.15分割線------------------------------------------------------------------------

跑了30個小時之後我發現loss依然很大accuracy依然很小,和開始並沒有區別我的天啊o( ̄ヘ ̄o#) 現在直接暫停了這個訓練開始找原因,找出原因後會及時更新的…… -----------------------------------------------------------------8.15分割線-------------------------------------------------------------------------
大概知道是什麼問題了,本來我以為我的方法和其他網上的部落格的方法都一樣是不會出問題的,現在看來真的都是那個大家都介紹的方法出問題了。不然為什麼沒有人把結果貼圖貼出來呢? o( ̄ヘ ̄o#) 這個問題是這樣的,出在第8步預訓練的VGG16的weights的傳遞過程中,咱們之前把VGG16卷積層的weights拷過去了,然後由於FCN是把全連線層都改成了卷積層,所以我們對於FC6和FC7的處理是直接不要它的權重初值。 就如同我上面第8步所寫,這裡是有問題的。至於什麼問題,我目前是認為那兩個層沒有設定初始權重導致無法收斂,更為細節的原因我還需要再研究一下 正確的步驟如下: ①我們首先應該執行一下這個資料夾(fcn.berkeleyvision.org/pascalcontext-fcn32s/)裡的 net.py 直接輸入 python net.py 這個的作用就是把train.prototxt 和val.prototxt按照net.py中所描述的細節設定一遍,你可以理解為把網路和各個Layer初始化一遍,執行完這個之後,你再去看那兩個prototxt,應該會發現之前被改動的fc6,fc7又改回來了; ②還是把那兩個prototxt中的資料來源改一下,這個是可以改動的,就如第6步中所述,改成你自己合適的路徑; 重點來了,更改solve.py
  1. import sys  
  2. import caffe  
  3. import surgery, score  
  4. import numpy as np  
  5. import os  
  6. import sys  
  7. try:  
  8.     import setproctitle  
  9.     setproctitle.setproctitle(os.path.basename(os.getcwd()))  
  10. except:  
  11.     pass  
  12. ###############################                                //這兩行是我們需要增加的
  13. vgg_weights ='../../VGG16/vgg16-fcn.caffemodel'//路徑請根據自己的位置修改就好
  14. vgg_proto = '../../VGG16/VGG_ILSVRC_16_layers_deploy.prototxt'//路徑請根據自己的位置修改
  15. ##############################
  16. # weights = '../vgg16-fcn.caffemodel'  //這個是原來的操作,註釋掉
  17. # init
  18. caffe.set_device(int(sys.argv[1]))  
  19. caffe.set_mode_gpu()  
  20. solver = caffe.SGDSolver('solver.prototxt')  
  21. # solver.net.copy_from(weights)        //這個也是原來的操作,註釋掉
  22. vgg_net = caffe.Net(vgg_proto,vgg_weights,caffe.TRAIN)  //這裡開始的3行都是我們需要增加的
  23. surgery.transplant(solver.net,vgg_net)  
  24. del vgg_net  
  25. # surgeries
  26. interp_layers = [k for k in solver.net.params.keys() if'up' in k]  
  27. surgery.interp(solver.net, interp_layers)  
  28. # scoring
  29. val = np.loadtxt('../data/pascal/VOC2010/ImageSets/Main/val.txt', dtype=str)  
  30. for _ in range(50):  
  31.     solver.step(8000)  
  32.     score.seg_tests(solver, False, val, layer='score')  
  33. ~  
  34. ~  
  35. ~  
  36. ~  


④我們這裡需要用到 vgg16-fcn.caffemodel 和VGG_ILSVRC_16_layers_deploy.prototxt caffemodel我們之前已經下載了,prototxt這個其實github上可以搜到,很多的,順手給個連結把: 然後把這兩個檔案放到你sovle.py中寫的對應位置去即可 至於為什麼這麼改? 其實它是先把這個權重值放到了VGG16的網路中,就是vgg_net = caffe.Net(vgg_proto,vgg_weights,caffe.TRAIN)這一句話 然後把vgg_net的權值通過一個函式轉化到我現在這個solver.net裡面去,surgery.transplant(solver.net,vgg_net) 就是這麼一個過程,附上transplant函式的原始碼以供參考
然後就ok了 輸入 python solve.py 0 附上一張成功轉換權值的過程圖
可以看到fc6和fc7的權重也被合理reshape之後coercing過去了 ⑥看一下現在的loss下降的速度 開始時:
1個小時後:
才一個小時就下降到十八萬了,這回感覺沒毛病了,就等過幾天跑完來更新博文了。 -----------------------------------------------------------------8.18分割線--------------------------------------------------------------------------
8-18 14:30的seg tests情況,overall accuracy已經達到了66.06%,mean accuracy達到了49.43%左右。 可見的確是精度在提高,但是真的感覺訓練速度很慢,我的Tesla K40C現在用了67個小時了,也才只完了112000迭代,而迭代總數設定的是30 0000, 也就是說如果跑完的話,估計需要180多個小時,粗略的估計是7--8天左右,我的神啊…… --------------------------------------------------------------------8.31分割線------------------------------------------------------------------ 最近開學太忙忘了更了,現在貼上最終的結果:
可以看到結果穩定在0.664左右,這與之前的作者給出的準確率是差不多一樣的,就百分位上有些小小的區別 作者論文結果如圖: