1. 程式人生 > >微調CaffeNet用於車顏色識別

微調CaffeNet用於車顏色識別

說明:主要思想是微調使用ImageNet預訓練的CaffeNet模型引數,用來對車顏色進行識別。為了不和其他檔案混亂,我們在examples下新建資料夾finetune_myself。

1.計算影象均值

caffenet需要影象均值檔案,所以先計算均值檔案。在finetune_myself下新建資料夾Image_mean,從imagenet中拷貝make_imagenet_mean.sh到finetune_myself下,更名為make_image_mean.sh(為了和imagenet區分),然後修改指令碼如下:

EXAMPLE=examples/finetune_myself #該路徑下為訓練影象的lmdb檔案
DATA=examples/finetune_myself/Image_mean #該路徑為生成的均值檔案儲存的地方
TOOLS=build/tools

$TOOLS/compute_image_mean $EXAMPLE/car_train_lmdb \ #這裡的lmdb和自己的對應
  $DATA/image_mean.binaryproto #生成的均值檔名字,這裡為了區分改一下名字

這樣,生成的均值檔案儲存在finetune_myself下的Image_mean資料夾裡,名字為image_mean.binaryproto。

2.準備caffenet模型

在finetune_myself下新建資料夾,命名為models,將caffenet的train_val.prototxt、solver.prototxt和deploy.prototxt複製到此models資料夾裡,然後,對模型進行修改。假設我們的訓練集類別是m,那麼fc8層的num_output需要修改成m,又由於finetune時用到的權重是根據層名匹配的,而fc8的num_output已經修改,該層的引數必須重新學習,所以我們把該層的名字也進行修改,如改為fc8_myself。具體修改如下。

對train_val.prototxt的修改:

(1) mean_file路徑:"examples/finetune_myself/Image_mean/image_mean.binaryproto"


訓練和測試階段的data層均要修改。

(2)假設訓練集和測試集的lmdb檔案在finetune_myself下,所以訓練階段的的data層:

data_param {
 source:"examples/finetune_myself/car_train_lmdb"
 batch_size: 50 #這裡自己可以修改合適的batch大小
 backend:LMDB
}

同理,TEST階段的data層也作同樣的修改。即:

data_param{
    source: "examples/finetune_myself/car_test_lmdb"
    batch_size:50
    backend:LMDB
  }

(3)修改fc8層和相關層

將層名改為fc8_myself(當然其他也行),並修改權重的lr_mult=10,bias的lr_mult=20,目的是讓非微調層學習更快。num_output修改為類別數。具體如下:

layer {
  name: "fc8_myself"
  type: "InnerProduct"
  bottom: "fc7"
  top: "fc8_myself"
  param {
    lr_mult: 10
    decay_mult: 1
  }
  param {
    lr_mult: 20
    decay_mult: 0
  }
  inner_product_param {
    num_output: 8  #根據類別修改,我做的實驗為8類
    weight_filler {
      type: "gaussian"
      std: 0.01
    }
    bias_filler {
      type: "constant"
      value: 0
    }
  }
}
與fc8相關的層也要修改:
layer {
  name:"accuracy"
  type:"Accuracy"
  bottom: "fc8_myself"
  bottom:"label"
  top:"accuracy"
  include {
  phase: TEST
  }
}
layer {
  name: "loss"
  type: "SoftmaxWithLoss"
  bottom: "fc8_myself"
  bottom: "label"
  top: "loss"
}

對solver.prototxt的修改:

主要是
net:"examples/finetune_myself/models/train_val.prototxt",

該路徑改為train_val.Prototxt的路徑。

還有

snapshot_prefix:"examples/finetune_myself/models/caffenet"

此路徑是訓練過程得到的caffemodel和solverstate儲存路徑,按自己想儲存的路徑更改。

對deploy.prototxt的修改:

網路的名字name要與train_val.prototxt相同。然後修改fc8層和相關層:

layer {
  name: "fc8_myself"
  type: "InnerProduct"
  bottom: "fc7"
  top: "fc8_myself"
  inner_product_param {
  num_output: 8 #根據類別數改
  }
}
layer {
  name:"prob"
  type:"Softmax"
  bottom: "fc8_myself"
  top:"prob"
}

這樣,模型就改好了。

3.準備預訓練好的caffenet模型引數

finetune_myself下新建資料夾pre_train_models,執行

./scripts/download_model_binary.py examples/finetune_myself/pre_train_models
即將檔案下載在pre_train_models中。

4.開始訓練

./build/tools/caffe train –solver examples/finetune_myself/models/solver.ptototxt –weights examples/finetune_myself/pre_train_models/bvlc_reference_caffenet

5.結果

訓練結果

精度還是挺高的。

訓練完成後,得到caffemodel檔案:
測試:
./build/examples/cpp_classification/classification.bin **/**/deploy.prototxt **/***/models_iter_100000.caffemodel **/**/image_mean.binaryproto **/**/labels.txt **/**/car.jpg

這些路徑按自己的設定,labels是標籤,比如你的train.txt中白色標籤是0,紅色標籤是1,那麼labels中第一行是white,第二行是red,其他的也是這樣按順序排。
結果:
white - "0.9963"
gray - "0.0036"
green - "0.0001"
輸出前三個預測結果