Caffe對MNIST數據進行Train、Test

用Caffe 訓練和測試MNIST數據:


1. 準備數據
1.1 運行腳本,從MNIST網站下載和轉換數據格式:
在Caffe安裝路徑下執行 /data/mnist: ./get_mnist.sh
              /examples/mnist: ./create_mnist.sh
1.2 運行完以上腳本後得到兩個數據集: mnist_train_lmdb,
      mnist_test_lmdb


2. 使用LeNet模型定義分類,但在我們的分類應用中,最初LeNet中的神經元由s型激活被替換成
   校正線性單元(ReLU)激活,一般說來LeNet包含convolutional layer,後面是pooling
   layer,另一個convolutional layer,緊跟pooling layer,然後將類似與卷及多層感知器
   的兩個層連接,上述層被定義在 /examples/mnist/lenet_train_test.prototxt


3. 定義MNIST Network
   在/src/caffe/proto/caffe.proto中可以瞭解Caffe protobuf的定義,通常我們寫一個
   caffe::NetParameter(或者Python, caffe.proto.caffe_pb2.NetParameter),我們
   定義該network名稱 name: "LeNet"
3.1 寫Data Layer
   目前我們從之前創立的lmdb中讀取MNIST data,該數據層定義爲
layers {
  name: "mnist"
  type: DATA
  data_param {
source: "mnist_train_lmdb"
backend: LMDB
batch_size: 64
scale: 0.00390625
     }
   top: "data"
   top: "label"
      }
該layer名稱爲mnist, 類型爲data, 從給定的lmdb讀取數據。bactch size 爲64
scale輸入像素使得它們在[0,1)之間變化,0.00390625 = 1 / 256, 最後該層產生
兩個blobs,一個是data blob, 另一個是label blob


3.2 寫Convolution Layer
    定義地一層convolution layer:
layers {
  name: "conv1"
  tyoe: CONVOLUTION
  blobs_lr: 1.
  blobs_lr: 2.
  convolution_param {
num_output: 20
kernelsize: 5
stride: 1
weight_filler {
                     type: "xavier"    
     }
bias_filler  {
 type: "constant"
    }
   }
   bottom: "data"
   top: "conv1"
      }
該層接收data blob(由data layer提供),產生conv1 layer, 其產生 20 channels的
輸出, convolutional kernel size爲 5, 以 stride 爲 1 產生結果。

fillers允許我們隨機初始化weights和bias值,對於weight filler,我們使用 xavier
算法基於輸入輸出神經元數目來決定初始scale. 對於bias filler,我們僅僅初始化其爲常數,
default filling 值爲 0.


blobs_lr是 learning rate. 在該情況下, 我們會設置weight learning rate 和 solver在
runtime 期間給定的 learning rate相同, bias learning rate 通常比 weight learning
        rate 大2倍, 這會導致較好的 convergence rates.


3.3 寫Pooling Layer
    Pooling Layers通常比較容易去定義
layers {
  name: "pool1"
  type: POOLING
  pooling_param {
kernel_size: 2
stride: 2
pool: MAX
}
  bottom: "conv1"
  top: "pool1"
      }
該層定義表明我們以kernel size爲2, stride 爲2(因此在neighboring poolings regions
之間沒有c重疊)來執行max pooling


類似地,你還可以定義第二個covolution和pooling layers, 具體可參考
/examples/mnist/lenet_train_test.prototxt


3.4 寫Fully connected Layer
    Fully connected Layer也很簡單:
layers {
  name: "ip1"
  type: INNER_PRODUCT
  blobs_lr: 1.
  blobs_lr: 2.
  inner_product_param {
num_output: 500
weight_filler {
type: "xavier"
     }
bias_filler {
type: "constant"
   }
      }
  bottom: "pool2"
  top: "ip1"
      }


該層定義了Fully connected layer(因爲一些原因,Caffe稱該層爲一種innerproduct layer)
具有500個輸出


3.5 寫ReLU Layer
     ReLU Layer也很簡單:
layers {
  name: "relu1"
  type: RELU
  bottom: "ip1"
  top: "ip1"
      }
由於ReLU是一種element-wise操作, 我們可以做in-place去節約內存。僅僅給bottom和top blobs
相同的名字就能實現該目標,當然,我們不給其他layer Types使用duplicated blob名字。


在ReLU layer之後,我們可以寫另一個innerproduct layer:
layers {
  name: "ip2"
  type: INNER_PRODUCT
  blobs_lr: 1.
  blobs_lr: 2.
  inner_product_param {
num_output: 10
weight_filler {
type: "xavier"
     }
bias_filler {
type: "constant"
   }
      }
  bottom: "ip1"
  top: "ip2"
      }


3.6 寫Loss Layer
     最後寫loss
layers {
   name: “loss”
   type: SOFTMAX_LOSS
   bottom: "ip2"
   bottom: "label"
      }
softmax_loss layer結合softmax和multinomial logistic loss(節省時間和提高穩定性)
該層接收2個blobs,第一個預測,第二個由data layer提供的label. 第二個不會產生任何outputs
它所做的是計算loss function 的值, 當 backpropagation 開始的時候,report 該值,
並表明梯度爲ip2


3.6 寫Layer Rules
Layer definition可以包括是否以及何時在network definition中的rules
layers {
  //...layer definition...
  include: { phase: TRAIN }
      }
這是一個規則,基於當前network's state來控制network中的layer inclusion. 詳細可參考
/src/caffe/proto/caffe.proto
在以上的例子中,該layer包含在TRAIN階段,如果我們將TRAIN改爲TEST,那麼該layer就會被應用於
test 階段。lenet_train_test.prototxt有兩個DATA layers(定義爲不同的batch_size)
一個是training phase另一個是testing phase.並且,在TEST phase有一個ACCURACY layer
每100 次iteration就會報告model accuracy, 定義於lenet_solver.protxt.


4. 定義MNIST Solver
檢查在prototxt中每行的註釋解釋:
/examples/mnist/lenet_solver.prototxt:


5. 訓練和測試模型
5.1 在已經寫了network definition protobut和 solver protobuf files之後,cd到文件夾
   /examples/mnist僅僅執行:
./train_lenet.sh
PS: 運行腳本時注意腳本中的路徑要改成自己安裝caffe時的絕對路徑,否則會出錯

說明: 運行代碼初始化時,出現的信息包括每一層的詳細信息,其連接和輸出形狀,該信息有助於debugging.
初始化之後,開始training,基於solver setting,根據設置,每100次iterations將會打印出training
loss function,每1000次iterations將會測試network,出現的信息中,對於每一次training iteration
lr是iteration的learning rate, loss是training function,對於testing phase的輸出,
score 0 是精確度, scorce 1是 testing loss function.


5.2 經過幾分鐘後,Optimization Done信息出現表明訓練完成,最終的model,以二進制protobuf file
存儲在 lenet_iter_10000, 接下來你可以將此訓練模型用於實際的數據集。


6. GPU和CPU training 轉換
只需要在 lenet_solver.prototxt中 改成solver_mode:CPU,則實現從GPU向CPU的轉換訓練,對於
小數據集,CPU和GPU速度相差不大,當在大數據集上運行時,這種差距就會很顯著。


7. 總結lenet_solver.prototxt中的各參數含義
iteration: 數據進行一次前向-後向的訓練
batchsize: 每次迭代訓練圖片的數量
epoch: 1個epoch就是將所有的訓練圖像全部通過網絡訓練一次

例如:例子中1280000張圖片,batchsize=256,則1個epoch需要1280000/256=5000次iteration
它的max-iteration=450000,則共有450000/5000=90個epoch,而lr什麼時候衰減與stepsize
有關,減少多少與gamma有關,即:若stepsize=500, base-lr=0.01, gamma=0.1,則當迭代到
第一個500次時,lr第一次衰減,衰減後的lr=lr*gamma=0.01*0.1=0.001,以後重複該過程,所以
stepsize是lr的衰減步長,gamma是lr的衰減係數。在訓練過程中,每到一定的迭代次數都會test net,
這裏的迭代次數是由test-interval決定的,如test=1000,則每迭代1000次測試一遍網絡,而
test-size, test-iter, 和test圖片的數量決定了怎樣test, test-size決定了test時每次
迭代輸入圖片的數量,test-iter就是test所有的圖片的迭代次數,如:500張test圖片,test-iter=100
則test-size=5, 而solver文檔裏只需要根據test圖片總數量來設置test-iter,以及根據需要
設置test-interval即可。


8. 測試數據集
8.1 有三種接口可以進行測試數據,命令行、Python、MATLAB,本例中採用命令行進行測試,在
   /examples/mnist路徑下,執行:
./test_lenent.sh
   注意: test_lenent.sh腳本是自己根據train_lenet.sh腳本對照改寫的,具體腳本內容
   可參考Caffe官網tutorial/interfaces中TEST的講解

8.2 經過幾分鐘,測試數據成功,然後可以修改參數,再進行測試,並根據結果分析數據!


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章