[caffe學習筆記]用自己的資料進行訓練和測試
我今天嘗試製作一個自己的訓練資料集,參考薛開宇的學習方式,模仿搭建自己的資料庫。
1.因為我的電腦裡有整個ImageNet_ILSVRC2012的資料集,所以從訓練集ILSVRC2012_img_train中隨便選了兩種:bird和fowl2.生成標籤檔案列表,即生成 train.txt 和val.txt 檔案
3.將生成的 txt 檔案列表中的影象與train影象庫、val影象庫的影象相連線,生成lmdb格式檔案
1 資料準備
首先在caffe/data下新建資料夾myself,用於存放資料檔案和後面的caffe模型相關檔案。 然後在myself資料夾下建立build_lmdb和datatest兩個資料夾,其中build_lmdb資料夾用於存放生成的lmdb檔案,datatest資料夾存放原始圖片資料。在datatest下新建2個資料夾,train和val,其中train資料夾中存放待訓練的圖片,val資料夾中存放待測試的圖片。
在train資料夾下,又新建兩個資料夾,分別存放不同動物,bird和fowl,作為訓練集
其中,bird資料夾中,一共有1000張圖片,作為訓練集,fowl資料夾中,一共有260張圖片,作為訓練集。
上圖的檔名是我重新命名之後的樣子,重新命名檔案程式碼如下:
import os; def rename(): count=0; name="dog"; path='/home/jack/caffe/data/myself/train/dog'; filelist=os.listdir(path) for files in filelist: olddir=os.path.join(path,files); if os.path.isdir(olddir): continue; filename=os.path.splitext(files)[0]; filetype=os.path.splitext(files)[1]; newdir=os.path.join(path,name+str(count)+filetype); os.rename(olddir, newdir); count+=1; rename();
然後在終端執行:
cd caffe
python data/myself/datatest/train/name.py
同樣的,val資料夾中也新建兩個資料夾,分別存放不同動物,bird和fowl,作為測試集,其中,bird一共300張,fowl一共73張。
現在原始資料就已經準備好了。
2 生成train.txt 、val.txt
生成標籤檔案train.txt和val.txt需要兩個.sh指令檔案,程式碼如下,放在data/myself/datatest目錄下:
下面是生成train.txt標籤檔案的.sh檔案指令,檔名稱為creatlist_train.sh
- 其中DATA是train資料bird的目錄,DATA1是train資料fowl的目錄,DATASAVE是儲存標籤檔案train.txt的路徑
- -name bird*.jpg的意思指以bird開頭的圖片名字
- cut -d ‘/’ -f8-10是擷取圖片的路徑,調整-f後面的數字可設定幾級路徑
- sed “s/$/ 1/”是在其後面加上 1(空格和1)
- 然後cat的命令是將train1.txt檔案中的內容儲存到train.txt中
- rm命令是刪除上面生成的train1.txt
- 經過上面步驟,bird和fowl的標籤檔案就都放到了train.txt 中。
cd caffe
sh ./data/myself/datatest/creatlist_train.sh
# /usr/bin/env sh
DATA=/home/zender/caffe/data/myself/datatest/train/bird/
DATA1=/home/zender/caffe/data/myself/datatest/train/fowl/
DATASAVE=/home/zender/caffe/data/myself/datatest/
echo "Create train.txt..."
find $DATA -name bird*.JPEG | cut -d '/' -f8-10 | sed "s/$/ 1/">>$DATASAVE/train.txt
find $DATA1 -name fowl*.JPEG | cut -d '/' -f8-10 | sed "s/$/ 2/">>$DATASAVE/train1.txt
cat $DATASAVE/train1.txt>>$DATASAVE/train.txt
rm -rf $DATASAVE/train1.txt
echo "Done.."
以此就可以生成train.txt檔案了,見下圖下面是生val.txt標籤檔案的.sh檔案指令程式碼,檔名稱為creatlist_val.sh
# /usr/bin/env sh
DATA=/home/zender/caffe/data/myself/datatest/val/bird/
DATA1=/home/zender/caffe/data/myself/datatest/val/fowl/
DATASAVE=/home/zender/caffe/data/myself/datatest/
echo "Create val.txt..."
find $DATA -name bird*.JPEG | cut -d '/' -f8-10 | sed "s/$/ 1/">>$DATASAVE/val.txt
find $DATA1 -name fowl*.JPEG | cut -d '/' -f8-10 | sed "s/$/ 2/">>$DATASAVE/val1.txt
cat $DATASAVE/val1.txt>>$DATASAVE/val.txt
rm -rf $DATASAVE/val1.txt
echo "Done.."
以此就可以生成val.txt檔案了,見下圖
至此我們就已經完成了製作自己的資料集以及生成train.txt和val.txt
3 生成LMDB檔案
在caffe root/examples/imagenet中有個create_imagenet.sh檔案,我們將其複製到我們的build_lmdb資料夾下重新命名為create_mynet.sh,然後對其中需要修改的地方進行修改:- 其中EXAMPLE=examples/imagenet改為自己檔案的路徑,EXAMPLE=/home/zender/caffe/data/myself/build_lmdb,用來儲存生成的lmdb檔案
- DATA=data/ilsvrc12,改為自己的原始圖片路徑:DATA=/home/zender/caffe/data/myself/datatest
- TRAIN_DATA_ROOT和VAL_DATA_ROOT指的是訓練集和測試集的路徑,修改為:TRAIN_DATA_ROOT=/home/zender/caffe/data/myself/datatest/ VAL_DATA_ROOT=/home/zender/caffe/data/myself/datatest/這裡因為train.txt檔案和val.txt檔案的路徑是從datatest開始的
- TOOLS保持不變
- resize是調整其大小為256*256以適應net的輸入,因為我的資料集bird和fowl大小是不一樣的,所以需要resize
#!/usr/bin/env sh
# Create the imagenet lmdb inputs
# N.B. set the path to the imagenet train + val data dirs
set -e
EXAMPLE=/home/zender/caffe/data/myself/build_lmdb
DATA=/home/zender/caffe/data/myself/datatest
TOOLS=build/tools
TRAIN_DATA_ROOT=/home/zender/caffe/data/myself/datatest/
VAL_DATA_ROOT=/home/zender/caffe/data/myself/datatest/
# Set RESIZE=true to resize the images to 256x256. Leave as false if images have
# already been resized using another tool.
RESIZE=true
if $RESIZE; then
RESIZE_HEIGHT=256
RESIZE_WIDTH=256
else
RESIZE_HEIGHT=0
RESIZE_WIDTH=0
fi
if [ ! -d "$TRAIN_DATA_ROOT" ]; then
echo "Error: TRAIN_DATA_ROOT is not a path to a directory: $TRAIN_DATA_ROOT"
echo "Set the TRAIN_DATA_ROOT variable in create_imagenet.sh to the path" \
"where the ImageNet training data is stored."
exit 1
fi
if [ ! -d "$VAL_DATA_ROOT" ]; then
echo "Error: VAL_DATA_ROOT is not a path to a directory: $VAL_DATA_ROOT"
echo "Set the VAL_DATA_ROOT variable in create_imagenet.sh to the path" \
"where the ImageNet validation data is stored."
exit 1
fi
echo "Creating train lmdb..."
GLOG_logtostderr=1 $TOOLS/convert_imageset \
--resize_height=$RESIZE_HEIGHT \
--resize_width=$RESIZE_WIDTH \
--shuffle \
$TRAIN_DATA_ROOT \
$DATA/train.txt \
$EXAMPLE/train_lmdb
echo "Creating val lmdb..."
GLOG_logtostderr=1 $TOOLS/convert_imageset \
--resize_height=$RESIZE_HEIGHT \
--resize_width=$RESIZE_WIDTH \
--shuffle \
$VAL_DATA_ROOT \
$DATA/val.txt \
$EXAMPLE/val_lmdb
echo "Done."
然後在終端裡面執行
cd caffe
./data/myself/build_lmdb/create_mynet.sh
注意:如果不在caffe的根目錄下執行,會報錯,所以需要先cd caffe
即可得到lmdb檔案
4 計算影象均值檔案
減去影象均值會獲得更好的效果,所以我們使用tools/compute_image_mean.cpp實現,這個cpp是一個很好的例子去熟悉如何操作多個組建,例如協議的緩衝區,leveldbs,登入等。
我們同樣複製/examples/imagenet的 make_imagenet_mean.sh檔案到data/myself/build_lmdb中,將其改名為creat_mymean.sh,加以修改路徑。
#!/usr/bin/env sh
# Compute the mean image from the imagenet training lmdb
# N.B. this is available in data/ilsvrc12
EXAMPLE=/home/zender/caffe/data/myself/build_lmdb
DATA=/home/zender/caffe/data/myself/datatest
TOOLS=build/tools
$TOOLS/compute_image_mean $EXAMPLE/train_lmdb \
$EXAMPLE/mymean.binaryproto
echo "Done."
其中,DATA用於儲存生成的 mymean.binaryproto檔案然後在終端裡面執行
cd caffe
./data/myself/build_lmdb/creat_mymean.sh
5 網路的定義
這個檔案是caffenet的模型配置檔案,裡面有輸入層、卷積層、池化層和全連層的定義,在這裡我們只需要對輸入層中的兩個位置進行修改。把caffe/models/bvlc_reference_caffenet中所有檔案複製到caffe/data/myself資料夾中,修改train_val.prototxt,注意修改資料層的路徑。如圖:
name: "CaffeNet"
layer {
name: "data"
type: "Data"
top: "data"
top: "label"
include {
phase: TRAIN
}
transform_param {
mirror: true
crop_size: 227
mean_file: "data/myself/build_lmdb/mymean.binaryproto"
}
# mean pixel / channel-wise mean instead of mean image
# transform_param {
# crop_size: 227
# mean_value: 104
# mean_value: 117
# mean_value: 123
# mirror: true
# }
data_param {
source: "data/myself/build_lmdb/train_lmdb"
batch_size: 256
backend: LMDB
}
}
layer {
name: "data"
type: "Data"
top: "data"
top: "label"
include {
phase: TEST
}
transform_param {
mirror: false
crop_size: 227
mean_file: "data/myself/build_lmdb/mymean.binaryproto"
}
# mean pixel / channel-wise mean instead of mean image
# transform_param {
# crop_size: 227
# mean_value: 104
# mean_value: 117
# mean_value: 123
# mirror: false
# }
data_param {
source: "data/myself/build_lmdb/val_lmdb"
batch_size: 50
backend: LMDB
}
}
再看下solver.prototxt檔案,其中:
1. net的路徑需要修改為自己的
2. snapshot_prefix的路徑是生成的模型放在哪裡
3. solver_mode: CPU 選擇CPU模式
4. 其餘的就根據自己的需要調整引數
net: "data/myself/train_val.prototxt"
test_iter: 10
test_interval: 100
base_lr: 0.001
lr_policy: "step"
gamma: 0.1
stepsize: 100
display: 20
max_iter: 400
momentum: 0.9
weight_decay: 0.0005
snapshot: 200
snapshot_prefix: "data/myself/"
solver_mode: CPU
使用下面的train_mynet.sh檔案來訓練caffenet模型,將其中的 –solver後面改成自己的路徑
#!/usr/bin/env sh
./build/tools/caffe train --solver=data/myself/solver.prototxt
6.進行訓練
在Linux終端下輸入下面的程式碼進行訓練
cd caffe
./data/myself/train_mynet.sh
由於我選擇使用CPU進行訓練,所以電腦特別卡,沒有訓練完就停止了
7 恢復資料
把caffe-master/examples/imagenet中的resume_training.sh複製到data/myself/build_lmdb資料夾下,修改檔案內容(倒數第二行,不是很確定):
#!/usr/bin/env sh
set -e
./build/tools/caffe train \
--solver=data/myself/solver.prototxt \
--snapshot=models/bvlc_reference_caffenet/myself_iter_2.caffemodel \
[email protected]
我們用指令./resume_training.sh即可。
8.出現的問題
1.caffe訓練遇到./build/tools/caffe: not found 錯誤解決方法
這是因為當前目錄在/caffe/data/myself/build_lmdb,而執行./create_mynet.sh ,需要在caffe目錄下,因此我們需要切換到caffe目錄下,然後執行
./data/myself/build_lmdb/create_mynet.sh
參考:
1.http://blog.csdn.net/fly_egg/article/details/53672592
2.http://blog.csdn.net/fly_egg/article/details/53670047
3.http://blog.csdn.net/u010194274/article/details/50575284
4.http://blog.csdn.net/thystar/article/details/51167334
5.http://blog.csdn.net/zhongshaoyy/article/details/53502373
6.http://blog.csdn.net/qqlu_did/article/details/47131549