CAFFE學習筆記(四)將自己的jpg數據轉成lmdb格式


1 引言

1-1 以example_mnist為例,如何加載屬於自己的測試集?

首先拋出一個問題:在example_mnist這個例子中,測試集是人家給好了的。那么如果我們想自己試着手寫幾個數字然后驗證識別效果又當如何呢?

觀察CAFFE_ROOT/examples/mnist/下的lenet_train_test.prototxt文件,發現里面既給出了訓練集的路徑,又給出了測試集的路徑。因此答案很顯然了,我們可以把自己的測試集做成leveldb(或lmdb)格式的,然后在lenet_train_test.prototxt中給出它的路徑,然后按照上一次博客說的那樣做即可。

1-2 如何將自己數據轉成leveldb/lmdb格式?幾個參考資料

如何將自己的訓練集和測試集(比方說一些寫着我們自己寫的數字的圖像)做成leveldb格式?

之所以需要轉格式,是因為我之后有一個想做的小實驗《用簡單的神經網絡來實現二元二次函數的擬合》,如此一來輸入的數據就得是leveldb或者lmdb格式,需要把這一點搞清楚才能獲取訓練集和測試集。這個問題我還沒有嘗試過,不過網上有很多博客有相關的說明,現在列幾個我覺得可以研讀一下的:

[1]CSDN博客《caffe神經網絡框架的輔助工具(將圖片轉為leveldb格式)》(該博客里面附有C++源碼,但是非常難懂);

[2]知乎問題《caffe下如何把自己的數據轉成lmdb或者leveldb-beanfrog的回答》(里面有python代碼,但牽扯到更多不熟悉的問題,還要先研究一下caffe怎么在python中用,比如被import的caffe包如何生成?)。

[3]薛開宇《學習筆記3用自己的數據訓練和測試“CaffeNet”》(本次博客我就是參考他的內容,他的這個博客是[4]的詳細版,寫的很好)。

[4]caffe官網《Caffe|ImageNet tutorial》(其開頭有這么一段話:This guide is meant to get you ready to train your own model on your own data.)

2 動手將自己的圖像數據轉成lmdb格式

2-1 獲取一個文件夾內全部圖像的名稱

(1)首先新建一個文件夾叫“批量名稱”,然后在里面放上若干圖片:

 

(2)接下來開始菜單→cmd,一路cd索引路徑直到目錄“批量名稱”下:

 

(3)輸入命令“dir/s/on/b>d:/train.txt”,則會在D盤生成一個名為train的文本文件,里面存放着“批量名稱”中全部圖像的路徑。

 

(4)可以使用查找與替換功能,使得上面的內容被修改為“文件名 label”的形式:

①索引“C:\Users\LJJ\Desktop\測試圖\caffe實驗\批量名稱\”替換成空。

相當於把這些路徑去掉,只保留文件名;

②索引“jpg”替換成“jpg 1”。這里1是label,指代了圖像的類別。

 

一個小技巧就是先不要把所有的訓練數據都混合放,而是分門別類放在各自的文件夾中。比如對於手寫數字,我們應該建立10個文件夾,然后把0全部放在一個文件夾“0”,1全部放在一個文件夾“1”……

接下來用剛才(3)中的指令給每個文件夾中的圖像都分別建立一個txt文件用於存放圖像名,最后建立好后將得到train0.txt~train9.txt十個文件。對每一個txt文件,按照其所屬類別,然后查找與替換的時候替換成的內容也是不一樣的。比如對於train3.txt,我們就要查找“jpg”替換成“jpg 3”,對於train5.txt,我們就要查找“jpg”替換成“jpg 5”。

當所有的train0.txt~train9.txt全部查找與替換完畢后,再將它們整合到一個txt文檔中命名為train.txt即可。

2-2 將任意大小的圖像resize成256*256

官網和薛開宇的筆記都給出了一段代碼,說可以通過把它做成sh文件並運行就可以將圖像轉成256*256的,但是我試了好久都沒成功。

為了達到目的,我決定曲線救國,用opencv里提供的cvResize函數來完成這一項。之所以選擇opencv是因為之前我的畢業設計用的是opencv所以比較熟悉,看網上更多人用的是matlab,有機會也可以一試。

由於這里詳細寫起來也是一篇博客的篇幅,所以我另外開了一個博客專門講這個問題,請移步《OpenCV玩耍(一)批量resize一個文件夾里的所有圖像》。

2-3 生成convert_imageset.exe

在CAFFE_ROOT目錄下有一個文件夾叫tools,里面有一個cpp文件叫convert_imageset.cpp,利用這個cpp文件生成一個exe文件convert_imageset.exe。具體的做法請移步《CAFFE學習筆記(三)在VS2013下生成需要的exe文件》。

2-4 生成lmdb文件

在data目錄下創建一個文件夾叫myself,這里把雜七雜八跟本次活動有關的文件全部放進來,有:訓練集train(一個放了所有訓練圖片的文件夾),測試集val(一個放了所有測試圖片的文件夾),train.txt,val.txt,test.txt。其中后兩者的文件名完全相同,只不過val.txt帶標簽,而test.txt不帶標簽。

將CAFFE_ROOT\examples\imagenet下一個叫create_imagenet.sh的文件拷貝到myself下,然后對里面的路徑進行設定。

 

 

這里用到的思想跟之前在《OpenCV玩耍(一)批量resize一個文件夾里的所有圖像》中說過的一樣,都是字符串拼接。其中DATA、TOOLS皆為路徑頭,得和后面的文件名組合起來才是完全路徑。說白了,就是在GLOG下分別給訓練集和測試集填寫三個絕對路徑+一個將要生成的文件夾名,這三個絕對路徑分別為:

(1)convert_imageset.exe的絕對路徑;

(2)train.txt/val.txt的絕對路徑;

(3)存放着圖片的訓練集train文件夾/測試集val文件夾的絕對路徑。

而上面關於resize的那段代碼實際上可以去掉不要了,因為事先我們已經resize過圖像了。一個簡化版的create_imagenet.sh可按如下來寫,其跑出的效果是一模一樣的:

 

完成路徑設定之后,雙擊該sh文件,即可在myself文件夾下生成imagenet_train_lmdb與 imagenet_val_lmdb文件夾。

3 尚未解決的問題

3-1 生成lmdb文件時報check failure

在生成lmdb文件的時候,其日志如下:

Creating train lmdb...

*** Check failure stack trace: ***

I0512 16:23:45.290897  1184 convert_imageset.cpp:83] Shuffling data

I0512 16:23:45.290897  1184 common.cpp:32] System entropy source not available, using fallback algorithm to generate seed instead.

I0512 16:23:45.290897  1184 convert_imageset.cpp:86] A total of 12 images.

F0512 16:23:45.306498  1184 db_lmdb.hpp:14] Check failed: mdb_status == 0 (112 vs. 0)

Creating val lmdb...

*** Check failure stack trace: ***

I0512 16:23:45.509299  3544 convert_imageset.cpp:83] Shuffling data

I0512 16:23:45.509299  3544 common.cpp:32] System entropy source not available, using fallback algorithm to generate seed instead.

I0512 16:23:45.509299  3544 convert_imageset.cpp:86] A total of 4 images.

F0512 16:23:45.509299  3544 db_lmdb.hpp:14] Check failed: mdb_status == 0 (112 vs. 0)

Done.

說是有“check failed”,那么這種檢查失敗是否會對生成的lmdb文件有影響?這種錯誤的出現是否跟之前配置時我把“在db.cpp中作如下修改...CHECK_EQ”這一步都去掉了有關?又如何能消除這個錯誤呢?

3-2 拿訓練好的lenet網絡測試該lmdb文件,失敗

嘗試用這種方法生成了一批手寫數字(含標簽)的lmdb文件,然后用caffe第二次博客中說的方法拿訓練好的網絡lenet_iter_10000.caffemodel對該lmdb文件進行測試,一看結果就是失敗的,其日志如下:

(前面的日志一切正常,我從打開lmdb開始截)

I0512 17:13:10.089304   188 db_lmdb.cpp:38] Opened lmdb

D:/MachineLearning/CAFFE_ROOT/data/myself/imagenet_train_lmdb

I0512 17:13:10.089304   188 data_reader.cpp:114] Restarting data prefetching from start.

F0512 17:13:10.089304  2492 data_transformer.cpp:465] Check failed: datum_channels > 0 (0 vs. 0)

I0512 17:13:10.089304   188 data_reader.cpp:114] Restarting data prefetching from start.

I0512 17:13:10.089304   188 data_reader.cpp:114] Restarting data prefetching from start.

重點是不知道測試數據是怎么做的,帶標簽還是不帶標簽?val.txt與test.txt分別用在何處?為什么在生成lmdb文件時只使用了val.txt而沒有用到test.txt?那test.txt又該用到什么地方呢?這些問題先懸掛在這里,我准備老老實實跟着薛開宇的第三次筆記做一遍再說。

3-3 如何生成leveldb文件?

本次試驗生成的是lmdb文件,但是就leveldb文件如何生成,在配置文件create_imagenet.sh中並沒有相應的選項。那答案是否能在convert_imageset.cpp中找到呢?

希望在后續學習中能解決以上這三個問題。

2016.5.12

by 悠望南山


免責聲明!

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



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