Caffe學習系列(23):如何將別人訓練好的model用到本身的數據上

caffe團隊用imagenet圖片進行訓練,迭代30多萬次,訓練出來一個model。這個model將圖片分爲1000類,應該是目前爲止最好的圖片分類model了。html

假設我如今有一些本身的圖片想進行分類,但樣本量過小,可能只有幾百張,而通常深度學習都要求樣本量在1萬以上,所以訓練出來的model精度過低,根本用不上,那怎麼辦呢?git

那就用caffe團隊提供給咱們的model吧。瀏覽器

由於訓練好的model裏面存放的就是一些參數,所以咱們實際上就是把別人預先訓練好的參數,拿來做爲咱們的初始化參數,而不須要再去隨機初始化了。圖片的整個訓練過程,說白了就是將初始化參數不斷更新到最優的參數的一個過程,既然這個過程別人已經幫咱們作了,並且比咱們作得更好,那爲何不用他們的成果呢?網絡

使用別人訓練好的參數,必須有一個前提,那就是必須和別人用同一個network,由於參數是根據network而來的。固然,最後一層,咱們是能夠修改的,由於咱們的數據可能並無1000類,而只有幾類。咱們把最後一層的輸出類別改一下,而後把層的名稱改一下就能夠了。最後用別人的參數、修改後的network和咱們本身的數據,再進行訓練,使得參數適應咱們的數據,這樣一個過程,一般稱之爲微調(fine tuning).ide

既然前兩篇文章咱們已經講過使用digits來進行訓練和可視化,這樣一個神器怎麼能不使用呢?所以本文以此工具爲例,講解整個微調訓練過程。工具

1、下載model參數post

能夠直接在瀏覽器裏輸入地址下載,也能夠運行腳本文件下載。下載地址爲:http://dl.caffe.berkeleyvision.org/bvlc_reference_caffenet.caffemodel學習

文件名稱爲:bvlc_reference_caffenet.caffemodel,文件大小爲230M左右,爲了代碼的統一,將這個caffemodel文件下載到caffe根目錄下的 models/bvlc_reference_caffenet/ 文件夾下面。也能夠運行腳本文件進行下載:測試

# sudo ./scripts/download_model_binary.py models/bvlc_reference_caffenet

 2、準備數據this

若是有本身的數據最好,若是沒有,能夠下載個人練習數據:http://pan.baidu.com/s/1MotUe

這些數據共有500張圖片,分爲大巴車、恐龍、大象、鮮花和馬五個類,每一個類100張。編號分別以3,4,5,6,7開頭,各爲一類。我從其中每類選出20張做爲測試,其他80張做爲訓練。所以最終訓練圖片400張(放在train文件夾內,每一個類一個子文件夾),測試圖片100張(放在test文件夾內,每一個類一個子文件夾)。

將圖片下載下來後解壓,放在一個文件夾內。好比我在當前用戶根目錄下建立了一個data文件夾,專門用來存放數據,所以個人訓練圖片路徑爲:/home/xxx/data/re/train

打開瀏覽器,運行digits,若是沒有這個工具的,推薦安裝,真的是學習caffe的神器。安裝及使用可參見個人前兩篇文章:Caffe學習系列(21):caffe圖形化操做工具digits的安裝與運行

新建一個classification dataset,設置以下圖:

下面圖片格式選爲jpg, 爲dataset取一個名字,就開始轉換吧。結果如圖:

3、設置model

回到digits根目錄,新建一個classification model, 選中你的dataset, 開始設置最重要的network.

 

caffenet的網絡配置文件,放在 caffe/models/bvlc_reference_caffenet/ 這個文件夾裏面,名字叫train_val.prototxt。打開這個文件,將裏面的內容複製到上圖的Custom Network文本框裏,而後進行修改,主要修改這幾個地方:

一、修改train階段的data層爲:

layer {
  name: "data"
  type: "Data"
  top: "data"
  top: "label"
  include {
    phase: TRAIN
  }
  transform_param {
    mirror: true
    crop_size: 227
  }
}

即把均值文件(mean_file)、數據源文件(source)、批次大小(batch_size)和數據源格式(backend)這四項都刪除了。由於這四項系統會根據dataset和頁面左邊「solver options"的設置自動生成。

二、修改test階段的data層:

layer {
  name: "data"
  type: "Data"
  top: "data"
  top: "label"
  include {
    phase: TEST
  }
  transform_param {
    mirror: false
    crop_size: 227
  }
}

和上面同樣,也是刪除那些項。

三、修改最後一個全鏈接層(fc8):

layer {
  name: "fc8-re"               #原來爲"fc8"
  type: "InnerProduct"
  bottom: "fc7"
  top: "fc8"
  param {
    lr_mult: 1.0
    decay_mult: 1.0
  }
  param {
    lr_mult: 2.0
    decay_mult: 0.0
  }
  inner_product_param {
    num_output: 5        #原來爲"1000"
    weight_filler {
      type: "gaussian"
      std: 0.01
    }
    bias_filler {
      type: "constant"
      value: 0.0
    }
  }
}

看註釋的地方,就只有兩個地方修改,其它不變。

設置好後,就能夠開始微調了(fine tuning).

訓練結果就是一個新的model,能夠用來單張圖片和多張圖片測試。具體測試方法前一篇文章已講過,在此就不重複了。

在此,將別人訓練好的model用到咱們本身的圖片分類上,整個微調過程就是這樣了。若是你不用digits,而直接用命令操做,那就更簡單,只須要修改一個train_val.prototxt的配置文件就能夠了,其它都是同樣的操做。

 

2016.12.6更新

這篇文章是將近一年前寫的,digits版本已經升級,因此有些地方設置有點變化,致使不少網友出現錯誤。最多的錯誤提示以下:

ERROR: Layer 'accuracy' references bottom 'label' at the TEST stage however this blob is not included at that stage. Please consider using an include directive to limit the scope of this layer.

我當時用的版本是digits 3.0, 如今你們用的是digits 4.0, 所以會出現這個錯誤。修改以下:

最後四層的設置:

layer {
  name: "re-fc8"
  type: "InnerProduct"
  bottom: "fc7"
  top: "fc8"
  param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  inner_product_param {
    
    weight_filler {
      type: "gaussian"
      std: 0.01
    }
    bias_filler {
      type: "constant"
      value: 0
    }
  }
}
layer {
  name: "accuracy"
  type: "Accuracy"
  bottom: "fc8"
  bottom: "label"
  top: "accuracy"
  include {
     stage:"val"
  }
}
layer {
  name: "loss"
  type: "SoftmaxWithLoss"
  bottom: "fc8"
  bottom: "label"
  top: "loss"
  exclude{
      stage:"deploy"
      }
}
layer {
  name: "prob"
  type: "Softmax"
  bottom: "fc8"
  top: "prob"
  include{
      stage:"deploy"
      }
}

  

原來網絡結構中的全鏈接層fc8, 須要改一下名字,如個人改爲"re-fc8". 由於咱們作的是微調。微調的意思就是先在別的數據集上進行訓練,把訓練好的權值,做爲咱們如今數據集的權值初始化,就再也不須要隨機初始化了。如今的數據和訓練時的數據不一致,所以有些層數的設置就會有點區別。好比這個例子中,用來訓練模型的數據集是imagenet,分爲1000類,而咱們的數據集就只有5類,所以在fc8這層上的num_output就會有區別,所以在這一層上就不能用人家的權值了,就須要把這層的名字改得和原來的網絡結構不同。

在digits 4.0版本中,最後的全鏈接層再也不須要num_output這個參數了,所以你們須要把這行刪除掉。digits會自動根據你的類別數把這個參數補充上。

也許原來的配置文件中沒有Softmax層,如今須要加上這一層,由於digits會根據這裏的設置自動生成train_test.prototxt和deploy.prototxt兩個文件。其它須要修改的地方,就是最後三層的include和exclude了。

最後還有一個問題就是顯存的問題。實話講個人這個訓練數據選得不太好,很吃顯存,有些GPU很差的同窗,運行起來很吃力。所以你們非要用這個數據的話,建議把batch_size調低些。我用的是nvidia k20, 4G顯存,batch_size設置爲16—32之間,運行得不錯,1分鐘左右運行完。

相關文章
相關標籤/搜索