Caffe小玩意
轉載自:http://blog.csdn.net/u014510375/article/details/51697946
Caffe小玩意(1)-可視化網絡結構
最近在學習Caffe,但是作為曾經的Windows深度用戶,還是比較習慣可視化的界面。然而,Caffe當然是在Linux/OS X系統下更好啦,因為一般還是寫script在命令行里面玩的。所以這樣就不直觀咯,為了能直觀地看清楚網絡結構,而不是看prototxt腦補…可視化就很重要了。?
幸好,開發Caffe的大神們已經考慮過這個問題了。在Caffe的根目錄下,有個python文件夾,里面有個draw_net.py,就是我們所需要的文件了。?
接下來我隨便挑了一個網絡結構。假設我們現在已經在這個python文件夾的路徑下,在命令行里,輸入
我用的是Macbook pro,在第一次運行的時候報錯了
pydot.InvocationException: GraphViz’s executables not found
查了一下發現我缺少了Graphviz這個專門用于畫圖的軟件,所以必須得裝一下。如果你裝了homebrew,那就簡單咯
<code class="language-bash hljs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">brew install graphviz</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul> 再次運行,就輸出了vis.png到當前路徑。打開看看:?
比較遺憾的是,對于自己定義的layer,目前貌似沒有辦法進行可視化(我嘗試了一下可視化Faster-RCNN結果失敗了)。之后我會再看看怎樣把自己定義的layer也可視化。
Caffe小玩意(2)-從caffemodel中導出參數
最近讀到一篇paper非常有意思,他們把caffe里訓練好的模型的參數導出來了,然后…弄到了torch里。所以,今天就來看看怎么導出參數吧。?
為了簡單,這次我選的是LeNet
從代碼里可以看得很清楚啦,首先導入模型,然后利用net.params就可以獲取參數了,另外你也可以利用net.data導出數據進行可視化。當然,在導出參數之前…你必須要跑過一遍,不然你沒有這個caffemodel…?
最后…要說一下我最近無聊的時候在github上開了個Naive-CNN的項目,就是….把Caffe里的模型參數導出來,用Matlab或者Python寫一遍。目前只做了LeNet。歡迎大家也來玩:?
https://github.com/Yuliang-Zou/Naive-CNN
Caffe小玩意(3)-利用py-faster-rcnn自定義輸入數據
眾所周知,caffe是現有deep learning framework中最為自動化的,我們甚至可以只定義prototxt文件而不需要寫代碼,就完成整個網絡的訓練。正是由于它的高度自動化,當我們想要修改其中的模塊,就不是一件容易的事了。?
caffe本身自帶了一些標準通用的dataset,我們可以比較簡單地使用它們。此外,對于一些其他的輸入形式,caffe也給出了一些指示:?
http://caffe.berkeleyvision.org/tutorial/data.html?
http://caffe.berkeleyvision.org/tutorial/layers.html#data-layers
但是,對于那種label不是簡單變量的輸入,我們應該怎么輸入到caffe里呢?(例如:顯著性檢測問題,我們的label應該是一幅灰度圖像;人體關節檢測問題,我們的label應該是一個tensor)。那么今天,我們就來看看如何利用rbg大神的py-faster-rcnn框架來自己定制輸入數據:?
https://github.com/rbgirshick/py-faster-rcnn
首先,pull這個repository到本地目錄(之后的./就代表在本地下的這個目錄),然后運行./data/目錄下的script下載數據(這些數據本身不是必要的,只是因為我之前需要finetune模型將它們下載了下來,之后的路徑、操作等等也基于這一事實)。
好了,現在會多了一些目錄出來。我們需要將數據(假設圖像輸入就是.jpg文件,label是python的numpy array,即.npy文件)放到相應的地方,即./data/VOCdevkit2007/VOC2007/JPEGImages。但是呢,這個目錄下是原來的VOC2007數據集的圖像輸入,所以我建議在這個目錄下再新建一個目錄(這里叫dlib)。因此實際存放路徑是:?
./data/VOCdevkit2007/VOC2007/JPEGImagesd/dlib
之后,我們需要為這些輸入數據寫xml文件。每一份輸入圖像都對應一個xml文件,內容如下(不需要注重格式):
<code class="language-xml hljs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">annotation</span>></span><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">folder</span>></span>VOC2007<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">folder</span>></span><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">filename</span>></span>image_0046.jpg<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">filename</span>></span><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">source</span>></span><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">database</span>></span>dlib facial landmark<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">database</span>></span><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">annotation</span>></span>Yuliang Zou<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">annotation</span>></span><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">source</span>></span><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">size</span>></span><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">width</span>></span>400<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">width</span>></span><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">height</span>></span>300<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">height</span>></span><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">depth</span>></span>3<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">depth</span>></span><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">size</span>></span><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">segmented</span>></span>0<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">segmented</span>></span><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">annotation</span>></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul> 同樣地,為了與原來數據的xml文件混淆,新建一個dlib文件夾,因此這些新xml文件的存放路徑為:?
./data/VOCdevkit2007/VOC2007/Annotations/dlib
以上的操作,都沒有對dataset進行training set與test set的區分,下面我們就來完成這件事。打開目錄:?
./data/VOCdevkit2007/VOC2007/ImageSets/Main?
我們可以看到很多的txt文件,先把原來的trainval.txt與test.txt備份好。然后,新建自己的trainval.txt與test.txt,每一行都是輸入圖像的名稱,例:?
dlib/100032540_1?
dlib/1002681492_1?
dlib/1004467229_1?
...?
(直接用這兩個txt文件的名字,是因為改用新的會有點麻煩,詳見附錄)
之后,我們需要修改相應的python代碼使得數據可以順利導入。?
(1)在lib/roi_data_layer/layer.py里的setup()函數,我們需要添加如下代碼,為label分配空間:
我這里的label是facial landmark,一共有68個2-d array。然后把下面的一些不需要的部分刪掉(不然之后可能會報錯)。
(2)在.lib/utils/blob.py里新定義一個函數:
<code class="language-python hljs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">def</span> <span class="hljs-title" style="box-sizing: border-box;">heatmap_list_to_blob</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(hms)</span>:</span><span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">""" Convert a list of heat maps into a network input."""</span>num_hms = len(hms)blob = np.zeros((num_hms, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">68</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">38</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">50</span>), dtype=np.float32)<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> i <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> xrange(num_hms):hm = hms[i]blob[i] = hm.transpose((<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>))<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> blob</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul>這個函數可以將包含若干label的python list轉換為caffe的blob數據結構。
(3)在lib/roi_data_layer/minibatch.py里導入剛剛定義的heatmap_list_to_blob函數,然后新定義函數:
<code class="language-python hljs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">def</span> <span class="hljs-title" style="box-sizing: border-box;">_get_heatmap_blob</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(roidb)</span>:</span><span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"""Get a batch of heat maps"""</span>num_images = len(roidb)hms = []<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> i <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> xrange(num_images):hm = np.load(roidb[i][<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'heatmap'</span>])hms.append(hm)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># Create a blob to hold the input heat maps</span>blob = heatmap_list_to_blob(hms)<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> blob</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li></ul>然后,在get_minibatch()函數中加入如下幾行代碼:
<code class="language-python hljs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># Get the imput heat map blob, formatted for caffe</span>hm_blob = _get_heatmap_blob(roidb)blobs[<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'heatmap'</span>] = hm_blob</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>(4)在./lib/roi_data_layer/roidb.py的prepare_roidb()函數中這行代碼之后:
<code class="language-python hljs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">roidb[i][<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'image'</span>] = imdb.image_path_at(i)</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>加入這么一行:
<code class="language-python hljs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">roidb[i][<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'heatmap'</span>] = roidb[i][<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'image'</span>][<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>:len(roidb[i][<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'image'</span>])-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>] + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'npy'</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>相信看到這里大家也知道了,imdb.image_path_at(i)獲取的是輸入圖像的完整路徑,我們進行些許修改就可以得到label的完整路徑。
最后,我們需要修改train.prototxt,這個按自己的需要定制就可以了,比較簡單,就不詳述了。
在最后之后,如果要測試性能,需要自己對./lib/fast_rcnn/test.py進行修改。這里不再詳述,我相信當你成功地開始訓練的時候,已經對這些內容比較了解了,可以比較容易地寫出自己需要的版本。
當然,完成了以上的所有步驟之后,可能還是會出現某些問題。?
1.畢竟我的xml文件比原來的簡化了不少,可以按實際情況刪掉相應的code(原來的代碼可能會導入xml文件的一些參數,但是我省略了那些參數)?
2.原來代碼對于輸入圖像的scaling比較奇怪,那邊有可能會出錯。對于某些輸入尺寸固定的dataset,或許你可以修改?
lib/roi_data_layer/layer.py里的setup()函數,其中會有一行?
top[idx].reshape(cfg.TRAIN.IMS_PER_BATCH, 3, _, _)?
最后的兩個參數是height和width,按需要修改。
最近折騰這個東西也折騰了很久,甚是頭疼,更是加深了我對rbg大神的仰慕之情。行文有些混亂,如果有不明白的歡迎留言,大家一起交流。
附錄:
./lib/datasets/factory.py這份代碼負責構造dataset?
line 15 - 20:
./experiments/scripts/faster_rcnn_end2end.sh這份bash文件負責指定訓練與測試時所用的dataset?
line 27 - 28:
總結
- 上一篇: 图解Android Studio 2.0
- 下一篇: Android中minSdkVersio