1. 程式人生 > >[caffe學習筆記]用自己的資料進行訓練和測試

[caffe學習筆記]用自己的資料進行訓練和測試

我今天嘗試製作一個自己的訓練資料集,參考薛開宇的學習方式,模仿搭建自己的資料庫。 

1.因為我的電腦裡有整個ImageNet_ILSVRC2012的資料集,所以從訓練集ILSVRC2012_img_train中隨便選了兩種:bird和fowl
2.生成標籤檔案列表,即生成 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

  1. 其中DATA是train資料bird的目錄,DATA1是train資料fowl的目錄,DATASAVE是儲存標籤檔案train.txt的路徑
  2. -name bird*.jpg的意思指以bird開頭的圖片名字
  3. cut -d ‘/’ -f8-10是擷取圖片的路徑,調整-f後面的數字可設定幾級路徑
  4. sed “s/$/ 1/”是在其後面加上 1(空格和1)
  5. 然後cat的命令是將train1.txt檔案中的內容儲存到train.txt中
  6. rm命令是刪除上面生成的train1.txt
  7. 經過上面步驟,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,然後對其中需要修改的地方進行修改:
  1. 其中EXAMPLE=examples/imagenet改為自己檔案的路徑,EXAMPLE=/home/zender/caffe/data/myself/build_lmdb,用來儲存生成的lmdb檔案
  2. DATA=data/ilsvrc12,改為自己的原始圖片路徑:DATA=/home/zender/caffe/data/myself/datatest
  3. 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開始的
  4. TOOLS保持不變
  5. 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