SSD演算法訓練

小魔大樹哥發表於2017-07-18
     沒接觸過linux,直接在linux下配置環境+訓練ssd,用了快一週時間,各種坑,各種吐血,因各人平臺配置差異,以下僅供參考。

       平臺:Ubuntu16.04+GTX1060 6G(GPU型號)+處理器64位
       CUDA:CUDA8.0,直接上Nvidia官方網站下載,選擇cuda_8.0.61_375.26_linux.run
       cuDNN:cuDNN,上Nvidia官網,註冊帳戶後下載,選擇cudnn-8.0-linux-x64-v6.0.tgz或cudnn-8.0-linux-x64-v5.1.tgz

一、安裝CUDA和cuDNN
       參見http://www.linuxidc.com/Linux/2016-12/138870.htm  其中注意幾點
       1、開始安裝依賴項時,libprotobuf-dev先不裝。因為這個依賴項對應到protobuf版本是2.6.1的。後面裝的protobuf是2.5.0版本。
       2、環境變數配置時,開啟~/.bashrc檔案,新增下面兩行到尾部,然後 soure ~/.bashrc使之生效
      export PATH=/usr/local/cuda-8.0/bin${PATH:+:${PATH}}
      export LD_LIBRARY_PATH=/usr/local/cuda-8.0/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
       3、安裝cuDNN時(6.0版本),解壓後得到lib64和include,把這兩個資料夾下到檔案拷貝到對應的CUDA安裝目錄下的lib64和include資料夾中。這裡cuda預設安裝目錄是/usr/local/cuda8.0,還有一個cuda資料夾,其實是連結到cuda8.0,所以路徑寫到這兩個資料夾都可以。
       4、建立軟連結,按照上面連結的說明,把libcudnn.so.5改成libcudnn.so.6,libcudnn.so.5.0.5改成libcudnn.so.6.0.21。
二、opencv我用opencv2.4.9版本。
以上是平臺的配置,要根據自己到軟體版本來修改,看上去很簡單,然鵝總是有很多報錯的,你只能不斷百度必應谷歌,歡迎交流。

三、caffe配置。

      1、boost安裝

下載boost的安裝包,解壓
tar -xjf boost_1_58_0.tar.bz2
在解壓目錄下執行
./bootstrap.sh
然後執行b2構建
sudo ./b2
成功會顯示
The Boost C++ Libraries were successfully built!
The following directory should be added to compiler include paths:
    /home/o/Boost庫/boost_1_58_0
The following directory should be added to linker library paths:
    /home/o/Boost庫/boost_1_58_0/stage/lib
如果沒有顯示這樣則執行
sudo apt-get install libbz2-dev
然後再
sudo ./bjam install
sudo ./b2
    2、安裝protobuf
    這裡有很多坑,一開始裝3.0.0版本,總是出現caffe.pb.h的錯或caffe.pb.o的錯,看這位兄臺,改成2.6版本解決問題,但是又出現其他問題,後面改為安裝2.5.0版本。
    安裝protobuf過程:
    下載protobuf2.5.0,解壓後看有沒有gtest資料夾,如果有就不用下載gtest-1.5.0了,如沒有,下載gtest-1.5.0後解壓放到protobuf下,然後重新命名為gtest。
cd protobuf
$ ./autogen.sh

執行上面程式碼得到configure檔案,然後
./configure -prefix=/usr   //這裡是你安裝的路徑,可以自己設定,一定要明確,後面新增環境變數要用。再執行

make
make check
sudo make install

安裝完成後新增環境變數,注意自己的路徑
sudo vim /etc/profile
####### add protobuf lib path ########
#(動態庫搜尋路徑) 程式載入執行期間查詢動態連結庫時指定除了系統預設路徑之外的其他路徑
如果是安裝在/usr中則用下面配置
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib/
#(靜態庫搜尋路徑) 程式編譯期間查詢動態連結庫時指定查詢共享庫的路徑
export LIBRARY_PATH=$LIBRARY_PATH:/usr/lib/
#執行程式搜尋路徑
export PATH=$PATH:/usr/bin/
#c程式標頭檔案搜尋路徑
export C_INCLUDE_PATH=$C_INCLUDE_PATH:/usr/include/
#c++程式標頭檔案搜尋路徑
export CPLUS_INCLUDE_PATH=$CPLUS_INCLUDE_PATH:/usr/include/
#pkg-config 路徑
export PKG_CONFIG_PATH=/usr/lib/pkgconfig/

source /etc/profile生效

完成後可以用protoc --version檢視版本。

如果要解除安裝protobuf,則可用先去除依賴項sudo apt-get remove libprotobuf-dev,再到原安裝的位置,一個一個刪除檔案。

     3、修改caffe下MakeFile和Makefile.config檔案配置,按照各人配置來修改。Makefile.config中,使用GPU當然就不用把# CPU_ONLY := 1這一行開啟, 使用cudnn則去掉前面的#,變為USE_CUDNN := 1,同樣#WITH_PYTHON_LAYER := 1開啟

參照http://www.linuxidc.com/Linux/2016-12/138870p2.htm,如果缺少什麼檔案,可能是沒安裝依賴項,或者沒包含相關標頭檔案,常見到錯誤網上一般答案很多。

# For CUDA < 6.0, comment the *_50 through *_61 lines for compatibility.
# For CUDA < 8.0, comment the *_60 and *_61 lines for compatibility.
CUDA_ARCH := -gencode arch=compute_20,code=sm_20 \
        -gencode arch=compute_20,code=sm_21 \
        -gencode arch=compute_30,code=sm_30 \
        -gencode arch=compute_35,code=sm_35 \
        -gencode arch=compute_50,code=sm_50 \
        -gencode arch=compute_52,code=sm_52 \
        -gencode arch=compute_60,code=sm_60 \
        -gencode arch=compute_61,code=sm_61 \
        -gencode arch=compute_61,code=compute_61

這裡意思是如果CUDA版本低於6.0則把50到61那幾行註釋,低於8.0則註釋60到61那3行。

python我用自帶的2.7版本,所以按安裝上面連結裡的路徑修改。


然後編譯

make all -j8或make all -j4,看自己機器幾核的。配置過程中在這裡停了好久,很多protobuf的錯誤在這邊出現,各人平臺不一樣,錯的也不一樣。

通過後再

sudo make runtest

這裡會跑很久

完成後配置caffe到python環境變數

sudo vim ~/.bashrc
export PYTHONPATH=~/caffe/python:$PYTHONPATH    //根據實際caffe路徑來寫
LD_LIBRARY_PATH=~/caffe/build/lib:$LD_LIBRARY_PATH
source ~/.bashrc  //使環境變數生效

很多人是配置sudo vi /etc/profile 這個檔案,查了下,~/.bashrc檔案是在當前使用者生效,profile則是對所有使用者生效。

如果出現

Traceback (most recent call last):
  File "/home/zc/caffe/data/VOC0712/../../scripts/create_annoset.py", line 103, in <module>
    label_map = caffe_pb2.LabelMap()
AttributeError: 'module' object has no attribute 'LabelMap'

可能沒有配置好環境變數。

到此caffe配置基本完成,其中可能會遇到很多問題,總結了一下,基本上是缺少依賴庫,版本不對,環境變數路徑不對這幾個問題。

python後

import pycaffe看看,如果換行沒報錯,則成功。

四、訓練ssd

      1、資料整理。比如3000張樣本,其中2000張作為訓練樣本train.txt,1000張作為測試樣本test.txt,這裡就沒有像VOC2007資料一樣還有trainval和val,假設你已經制作好xml檔案,還有兩個檔案train.txt, test.txt。裡面的內容為對應的影象名,不帶jpg字尾,一張影象一行。

00000

00001

00002


在caffe/data下新建ssdtrain和train_dataset資料夾,在ssdtrain下新建train_dataset資料夾,在ssdtrain/train_dataset下新建Annotations,ImageSets ,JPEGImages三個資料夾,在ImageSets下新建Layout,Main, Segmentation三個資料夾,上面train.txt, test.txt放在caffe/data/ssdtrain/train_dataset/ImageSet/Main下,所有xml檔案放在Annotations下,所有影象放在JPEGImages下。當然,這裡坑又來了,vim下開啟train.txt, test.txt看看他們到格式 :set ff,如果顯示是DOS,則設定為unix,:set ff=unix不然後面坑到你吐血。這個是windows和unix的換行符問題。
        2、修改create_data.sh ,labelmap_voc.prototxt ,create_list.sh三個檔案,見這裡http://www.cnblogs.com/zjutzz/p/6845002.html
        將VOC0712下這三個檔案複製到caffe/data/train_dataset下,改名為create_data_traindata.sh ,labelmap_traindata.prototxt ,create_list_traindata.sh,裡面的路徑要根據自己caffe的路徑修改,比如create_list_traindata.sh中root_dir = .../caffe/data/ssdtrain,可用絕對路徑

---------------------------------------------------------

create_list_traindata.sh:

root_dir=我的絕對路徑/caffe/data/ssdtrain
sub_dir=ImageSets/Main
bash_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
for dataset in train test
do
  dst_file=$bash_dir/$dataset.txt
  if [ -f $dst_file ]
  then
    rm -f $dst_file
  fi
  for name in train_dataset
  do
    if [[ $dataset == "test" && $name == "VOC2012" ]]
    then
      continue
    fi
    echo "Create list for $name $dataset..."
    dataset_file=$root_dir/$name/$sub_dir/$dataset.txt

    img_file=$bash_dir/$dataset"_img.txt"
    cp $dataset_file $img_file
    sed -i "s/^/$name\/JPEGImages\//g" $img_file
    sed -i "s/$/.jpg/g" $img_file

    label_file=$bash_dir/$dataset"_label.txt"
    cp $dataset_file $label_file
    sed -i "s/^/$name\/Annotations\//g" $label_file
    sed -i "s/$/.xml/g" $label_file

    paste -d' ' $img_file $label_file >> $dst_file

    rm -f $label_file
    rm -f $img_file
  done

  # Generate image name and size infomation.
  if [ $dataset == "test" ]
  then
    $bash_dir/../../build/tools/get_image_size $root_dir $dst_file $bash_dir/$dataset"_name_size.txt"
  fi

  # Shuffle trainval file.
  if [ $dataset == "train" ]
  then
    rand_file=$dst_file.random
    cat $dst_file | perl -MList::Util=shuffle -e 'print shuffle(<STDIN>);' > $rand_file
    mv $rand_file $dst_file
  fi
done

------------------------------------------------

create_data_traindata.sh:

cur_dir=$(cd $( dirname ${BASH_SOURCE[0]} ) && pwd )
root_dir=$cur_dir/../..
cd $root_dir
redo=1
data_root_dir="我的絕對路徑/caffe/data/ssdtrain"
#dataset_name="VOC0712"
dataset_name="train_dataset"
mapfile="$root_dir/data/$dataset_name/labelmap_traindata.prototxt"
anno_type="detection"
db="lmdb"
min_dim=0
max_dim=0
width=0
height=0

extra_cmd="--encode-type=jpg --encoded"
if [ $redo ]
then
  extra_cmd="$extra_cmd --redo"
fi
for subset in train test
do
  python $root_dir/scripts/create_annoset.py --anno-type=$anno_type --label-map-file=$mapfile --min-dim=$min_dim --max-dim=$max_dim --resize-width=$width --resize-height=$height --check-label $extra_cmd $data_root_dir $root_dir/data/$dataset_name/$subset.txt $data_root_dir/$dataset_name/$db/$dataset_name"_"$subset"_"$db examples/$dataset_name
done

-------------------------------------

labelmap_voc.prototxt:看你檢測任務來改

item {
  name: "none_of_the_above"
  label: 0
  display_name: "background"
}
item {
  name: "person"
  label: 1
  display_name: "person"
}

在caffe目錄下執行
./data/train_dataset/create_list_traindata.sh
會得到test_name_size.txt,train.txt,test.txt三個檔案,
train.txt,test.txt內容格式為對應的xml和影象檔案路徑
train_dataset/JPEGImages/02000.jpg train_dataset/Annotations/02000.xml
train_dataset/JPEGImages/02001.jpg train_dataset/Annotations/02001.xml
train_dataset/JPEGImages/02002.jpg train_dataset/Annotations/02002.xml
注意:這裡又有一個大坑和上面一樣,換行符問題,但可能顯示是unix格式,但是用vim
開啟檔案會有^M字元,如果你繼續執行./data/train_dataset/create_data_traindata.sh
可能出現找不到xml或jpg影象的錯誤。
解決辦法是刪除上面檔案中的^M,在vim下:%s/^M//g,回車,然後在caffe/examples下新建train_dataset資料夾,執行

./data/train_dataset/create_data_traindata.sh

會在caffe/examples/train_datasetcaffe/data/ssdtrain/train_dataset下生成lmdb檔案,內容一樣。

        3、修改ssd_pascal_traindata.py檔案

       把examples下ssd資料夾中的ssd_pascal.py檔案複製到caffe/examples/train_dataset下,修改為ssd_pascal_traindata.py,內容修改如下:

--------------------------------------------------------------------

# The database file for training data. Created by data/VOC0712/create_data.sh
train_data = "examples/train_dataset/train_dataset_train_lmdb"
# The database file for testing data. Created by data/VOC0712/create_data.sh
test_data = "examples/train_dataset/train_dataset_test_lmdb"

------------------------------------------------------------------

# Modify the job name if you want.
job_name = "SSD_{}".format(resize)
# The name of the model. Modify it if you want.
model_name = "VGG_train_dataset_{}".format(job_name)

# Directory which stores the model .prototxt file.
save_dir = "models/VGGNet/train_dataset/{}".format(job_name)
# Directory which stores the snapshot of models.
snapshot_dir = "models/VGGNet/train_dataset/{}".format(job_name)
# Directory which stores the job script and log file.
job_dir = "jobs/VGGNet/train_dataset/{}".format(job_name)
# Directory which stores the detection results.
output_result_dir = "{}/data/ssdtrain/result/train_dataset/{}/Main".format(os.environ['HOME'], job_name)

--------------------------------路徑按照自己的路徑--------------------------------------

# Stores the test image names and sizes. Created by data/VOC0712/create_list.sh
name_size_file = "data/train_dataset/test_name_size.txt"
# The pretrained model. We use the Fully convolutional reduced (atrous) VGGNet.
pretrain_model = "models/VGGNet/VGG_ILSVRC_16_layers_fc_reduced.caffemodel"
# Stores LabelMapItem.
label_map_file = "data/train_dataset/labelmap_traindata.prototxt"

-----------------類別數量如果是1類,加上背景,所以為2---------------------------

num_classes = 2

-------------------------------gpu設定---只有一個-------------------------------

# Defining which GPUs to use.
gpus = "0"

cd到caffe下

python examples/train_dataset/ssd_pascal_traindata.py

則會在caffe下生成jobs,model等資料夾和檔案,會提示找不到VGG_ILSVRC_16_layers_fc_reduced.caffemodel

下載預訓練模型VGG_ILSVRC_16_layers_fc_reduced.caffemodel放到models/VGGNet下。再次執行可能提示cudnn記憶體不足,把ssd_pascal_traindata.py中改為

# Divide the mini-batch to different GPUs.
#batch_size = 32
#accum_batch_size = 32
batch_size = 10
accum_batch_size = 10


訓練得到模型後在windows下vs工程中測試,把deploy.prototxt,labelmap_traindata.prototxt,solver.prototxt,test.prototxt,train.prototxe,VGG_train_dataset_SSD_300x300_iter_6000.caffemodel複製到vs工程下,修改

deploy.prototxt中最後save_output_param中,只留下label_map_file,並修改路徑。


在linux下編輯沒有上傳圖,等有空時再完善吧。歡迎交流討論。

參考:

http://www.linuxidc.com/Linux/2016-12/138870.htm

http://www.linuxidc.com/Linux/2016-12/138870p2.htm

http://blog.csdn.net/missdaddio/article/details/67631777

http://blog.csdn.net/xiexievv/article/details/47396725


-----------------------------------------20170915------------------------------------------------------------

訓練SSD512模型,batch_size和accum_batch_size相對於SSD300要減小,否則視訊記憶體不夠。batch_size減小後,訓練不易收斂。

相關文章