1. 程式人生 > >用自己的資料訓練和測試“caffenet”

用自己的資料訓練和測試“caffenet”

本次實驗本來參考examples/imagenet下的readme.txt進行,但因為資料集過於龐大,所以模擬學習,參考薛開宇的學習方式,模仿搭建自己的資料庫。
首先在caffe/data下新建資料夾myself,然後在網上下載貓、鳥、狗的訓練圖片各50張,測試圖片17,11,14張。為了方便,把圖片名修改,使用python,程式碼如下:

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();

這裡寫圖片描述

這裡寫圖片描述
重複使用下面這幾句話,最後將三類訓練資料的檔名都複製到一起。至於檔案格式為何要這樣.是參考data/ilsvrc12下的train.txt和val.txt.

 find train/dog -name *.JPEG |cut -d '/' -f2-3 >train.txt
 sed "s/$/ 2/" ./train.txt>./train1.txt

這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述
當然我這方法比較蠢,也可以寫指令碼檔案,或者使用python處理也是可以的。
此外還需要新增test.txt,內容和val.txt一致,不過最後面不跟分類標籤,而是0.
我們還需要把圖片的大小變成 256X256,但在一個叢集環境,可以不明確的進行,使用Mapreduce 就可以了,像楊青就是這樣做的。如果我們希望更簡單,用下面的命令:

for name in train/bird/*.JPEG ; do  convert -resize 256x256\! $name $name; done
for name in train/dog/*.JPEG ; do  convert -resize 256x256\! $name $name; done
for name in train/cat/*.JPEG ; do  convert -resize 256x256\! $name $name; done
for name in val/*.JPEG ; do  convert -resize 256x256\! $name $name; done

接下來在caffe/examples中新建myself資料夾,然後將caffe/examples/imagenet的create_imagenet.sh複製到該資料夾下,將其名改為create_myimagenet.sh,修改訓練和測試路徑的設定,執行該sh.如圖:
這裡寫圖片描述
如果出現錯誤./create_myimagenet.sh: 39: ./create_myimagenet.sh: build/tools/convert_imageset: not found
Creating val lmdb...
./create_myimagenet.sh: 49: ./create_myimagenet.sh: build/tools/convert_imageset: not found
Done.

說明路徑有問題,最好像我這樣補全。完成後在examples/myself下多出連個資料夾,如下圖
這裡寫圖片描述

2 計算影象均值
減去影象均值會獲得更好的效果,所以我們使用tools/compute_image_mean.cpp實現,這個cpp是一個很好的例子去熟悉如何操作多個組建,例如協議的緩衝區,leveldbs,登入等。我們同樣複製caffe-maester/examples/imagenet的
./make_imagenet_mean到examples/myself中,將其改名為make_myimagenet_mean.sh,加以修改路徑。
這裡寫圖片描述
不管如何修改檔名和路徑一定要對應,不然會有小問題出現。執行./make_myimagenet_mean.sh會在data/myself下出現myimagenet_mean.binaryproto檔案
3 網路的定義
把caffe/models/bvlc_reference_caffenet中所有檔案複製到caffe/examples/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/myimagenet_mean.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: "examples/myself/ilsvrc12_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/myimagenet_mean.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: "examples/myself/ilsvrc12_val_lmdb"
    batch_size: 50
    backend: LMDB
  }
}

從裡面可以觀察到,我們將執行256批次,迭代4500000次(90期),每1000次迭代,我們測試學習網路驗證資料,我們設定初始的學習率為0.01,每100000(20期)次迭代減少學習率,顯示一次資訊,訓練的weight_decay為0.0005,每10000次迭代,我們顯示一下當前狀態。
以上是教程的,實際上,以上需要耗費很長時間,因此,我們稍微改一下
test_iter: 1000是指測試的批次,我們就10張照片,設定10就可以了。
test_interval: 1000是指每1000次迭代測試一次,我們改成500次測試一次。
base_lr: 0.01是基礎學習率,因為資料量小,0.01就會下降太快了,因此改成0.001
lr_policy: “step”學習率變化
gamma: 0.1學習率變化的比率
stepsize: 100000每100000次迭代減少學習率
display: 20每20層顯示一次
max_iter: 450000最大迭代次數,
momentum: 0.9學習的引數,不用變
weight_decay: 0.0005學習的引數,不用變
snapshot: 10000每迭代10000次顯示狀態,這裡改為2000次
solver_mode: GPU末尾加一行,代表用GPU進行
如果出現錯誤cudasucess(2.0vs 0)out of memory之類的說明batchsize太大,我設定成4和5。然後如果訓練不收斂就重試,我試了三次,每次用的時間都超過15個小時,2.1計算能力的電腦就是差,今天總算完成了。這裡寫圖片描述
準確率並不高,可能是選的圖片不是很好,這個也有關係的,另外我是有三類和他們的兩類不一樣。訓練完成後結果存放在哪裡我也不是很清楚,只知道myself前一級資料夾下有很多類似
myself_iter_160.caffemodel的檔案出現。現在還不是很懂,此外還有檢視GPU狀態的指令nvidia-smi。實踐還是得跟進理論,不然很多東西都雲裡霧裡的。