天天看點

caffe配置檔案

一.資料層及參數

要運作caffe,需要先建立一個模型(model),如比較常用的Lenet,Alex等, 而一個模型由多個屋(layer)構成,每一屋又由許多參數組成。所有的參數都定義在caffe.proto這個檔案中。要熟練使用caffe,最重要的就是學會配置檔案(prototxt)的編寫。

層有很多種類型,比如Data,Convolution,Pooling等,層之間的資料流動是以Blobs的方式進行。

今天我們就先介紹一下資料層.

資料層是每個模型的最底層,是模型的入口,不僅提供資料的輸入,也提供資料從Blobs轉換成别的格式進行儲存輸出。通常資料的預處理(如減去均值, 放大縮小, 裁剪和鏡像等),也在這一層設定參數實作。

資料來源可以來自高效的資料庫(如LevelDB和LMDB),也可以直接來自于記憶體。如果不是很注重效率的話,資料也可來自磁盤的hdf5檔案和圖檔格式檔案。

所有的資料層的都具有的公用參數:先看示例

layer {

  name: "cifar"

  type: "Data"

  top: "data"

  top: "label"

  include {

    phase: TRAIN

  }

  transform_param {

    mean_file: "examples/cifar10/mean.binaryproto"

  }

  data_param {

    source: "examples/cifar10/cifar10_train_lmdb"

    batch_size: 100

    backend: LMDB

  }

}

name: 表示該層的名稱,可随意取

type: 層類型,如果是Data,表示資料來源于LevelDB或LMDB。根據資料的來源不同,資料層的類型也不同(後面會詳細闡述)。一般在練習的時候,我們都是采用的LevelDB或LMDB資料,是以層類型設定為Data。

top或bottom: 每一層用bottom來輸入資料,用top來輸出資料。如果隻有top沒有bottom,則此層隻有輸出,沒有輸入。反之亦然。如果有多個 top或多個bottom,表示有多個blobs資料的輸入和輸出。

data 與 label: 在資料層中,至少有一個命名為data的top。如果有第二個top,一般命名為label。 這種(data,label)配對是分類模型所必需的。

include: 一般訓練的時候和測試的時候,模型的層是不一樣的。該層(layer)是屬于訓練階段的層,還是屬于測試階段的層,需要用include來指定。如果沒有include參數,則表示該層既在訓練模型中,又在測試模型中。

Transformations: 資料的預處理,可以将資料變換到定義的範圍内。如設定scale為0.00390625,實際上就是1/255, 即将輸入資料由0-255歸一化到0-1之間

其它的資料預處理也在這個地方設定:

transform_param {

    scale: 0.00390625

    mean_file_size: "examples/cifar10/mean.binaryproto"

    # 用一個配置檔案來進行均值操作

    mirror: 1  # 1表示開啟鏡像,0表示關閉,也可用ture和false來表示

    # 剪裁一個 227*227的圖塊,在訓練階段随機剪裁,在測試階段從中間裁剪

    crop_size: 227

  }

在caffe中,如果定義了crop_size,那麼在train時會對大于crop_size的圖檔進行随機裁剪,而在test時隻是截取中間部分(詳見/caffe/src/caffe/data_transformer.cpp):

1、資料來自于資料庫(如LevelDB和LMDB)

層類型(layer type):Data

必須設定的參數:

  source: 包含資料庫的目錄名稱,如examples/mnist/mnist_train_lmdb

  batch_size: 每次處理的資料個數,如64

可選的參數:

  rand_skip: 在開始的時候,路過某個資料的輸入。通常對異步的SGD很有用。

  backend: 選擇是采用LevelDB還是LMDB, 預設是LevelDB.

示例:

layer {

  name: "mnist"

  type: "Data"

  top: "data"

  top: "label"

  include {

    phase: TRAIN

  }

  transform_param {

    scale: 0.00390625

  }

  data_param {

    source: "examples/mnist/mnist_train_lmdb"

    batch_size: 64

    backend: LMDB

  }

}

2、資料來自于記憶體

層類型:MemoryData

必須設定的參數:

 batch_size:每一次處理的資料個數,比如2

 channels:通道數

  height:高度

   width: 寬度

示例:

layer {

  top: "data"

  top: "label"

  name: "memory_data"

  type: "MemoryData"

  memory_data_param{

    batch_size: 2

    height: 100

    width: 100

    channels: 1

  }

  transform_param {

    scale: 0.0078125

    mean_file: "mean.proto"

    mirror: false

  }

}

3、資料來自于HDF5

層類型:HDF5Data

必須設定的參數:

source: 讀取的檔案名稱

batch_size: 每一次處理的資料個數

示例:

layer {

  name: "data"

  type: "HDF5Data"

  top: "data"

  top: "label"

  hdf5_data_param {

    source: "examples/hdf5_classification/data/train.txt"

    batch_size: 10

  }

}

4、資料來自于圖檔

層類型:ImageData

必須設定的參數:

  source: 一個文本檔案的名字,每一行給定一個圖檔檔案的名稱和标簽(label)

  batch_size: 每一次處理的資料個數,即圖檔數

可選參數:

  rand_skip: 在開始的時候,路過某個資料的輸入。通常對異步的SGD很有用。

  shuffle: 随機打亂順序,預設值為false

  new_height,new_width: 如果設定,則将圖檔進行resize

 示例:

layer {

  name: "data"

  type: "ImageData"

  top: "data"

  top: "label"

  transform_param {

    mirror: false

    crop_size: 227

    mean_file: "data/ilsvrc12/imagenet_mean.binaryproto"

  }

  image_data_param {

    source: "examples/_temp/file_list.txt"

    batch_size: 50

    new_height: 256

    new_width: 256

  }

}

5、資料來源于Windows

層類型:WindowData

必須設定的參數:

  source: 一個文本檔案的名字

  batch_size: 每一次處理的資料個數,即圖檔數

示例:

layer {

  name: "data"

  type: "WindowData"

  top: "data"

  top: "label"

  include {

    phase: TRAIN

  }

  transform_param {

    mirror: true

    crop_size: 227

    mean_file: "data/ilsvrc12/imagenet_mean.binaryproto"

  }

  window_data_param {

    source: "examples/finetune_pascal_detection/window_file_2007_trainval.txt"

    batch_size: 128

    fg_threshold: 0.5

    bg_threshold: 0.5

    fg_fraction: 0.25

    context_pad: 16

    crop_mode: "warp"

  }

}

二.視覺層(Vision Layers)及參數

本文隻講解視覺層(Vision Layers)的參數,視覺層包括Convolution, Pooling, Local Response Normalization (LRN), im2col等層。

1、Convolution層:

就是卷積層,是卷積神經網絡(CNN)的核心層。

層類型:Convolution

  lr_mult: 學習率的系數,最終的學習率是這個數乘以solver.prototxt配置檔案中的base_lr。如果有兩個lr_mult, 則第一個表示權值的學習率,第二個表示偏置項的學習率。一般偏置項的學習率是權值學習率的兩倍。

在後面的convolution_param中,我們可以設定卷積層的特有參數。

必須設定的參數:

    num_output: 卷積核(filter)的個數

    kernel_size: 卷積核的大小。如果卷積核的長和寬不等,需要用kernel_h和kernel_w分别設定

其它參數:

     stride: 卷積核的步長,預設為1。也可以用stride_h和stride_w來設定。

     pad: 擴充邊緣,預設為0,不擴充。 擴充的時候是左右、上下對稱的,比如卷積核的大小為5*5,那麼pad設定為2,則四個邊緣都擴充2個像素,即寬度和高度都擴充了4個像素,這樣卷積運算之後的特征圖就不會變小。也可以通過pad_h和pad_w來分别設定。

      weight_filler: 權值初始化。 預設為“constant",值全為0,很多時候我們用"xavier"算法來進行初始化,也可以設定為”gaussian"

      bias_filler: 偏置項的初始化。一般設定為"constant",值全為0。

      bias_term: 是否開啟偏置項,預設為true, 開啟

      group: 分組,預設為1組。如果大于1,我們限制卷積的連接配接操作在一個子集内。如果我們根據圖像的通道來分組,那麼第i個輸出分組隻能與第i個輸入分組進行連接配接。

輸入:n*c0*w0*h0

輸出:n*c1*w1*h1

其中,c1就是參數中的num_output,生成的特征圖個數

 w1=(w0+2*pad-kernel_size)/stride+1;

 h1=(h0+2*pad-kernel_size)/stride+1;

如果設定stride為1,前後兩次卷積部分存在重疊。如果設定pad=(kernel_size-1)/2,則運算後,寬度和高度不變。

示例:

layer {

  name: "conv1"

  type: "Convolution"

  bottom: "data"

  top: "conv1"

  param {

    lr_mult: 1

  }

  param {

    lr_mult: 2

  }

  convolution_param {

    num_output: 20

    kernel_size: 5

    stride: 1

    weight_filler {

      type: "xavier"

    }

    bias_filler {

      type: "constant"

    }

  }

}

2、Pooling層

也叫池化層,為了減少運算量和資料次元而設定的一種層。

層類型:Pooling

必須設定的參數:

     kernel_size: 池化的核大小,如何确定大小?。也可以用kernel_h和kernel_w分别設定。

其它參數:

   pool: 池化方法,預設為MAX。目前可用的方法有MAX, AVE, 或STOCHASTIC

  pad: 和卷積層的pad的一樣,進行邊緣擴充。預設為0

  stride: 池化的步長,預設為1。一般我們設定為2,即不重疊(步長=視窗大小)。也可以用stride_h和stride_w來設定。

 示例:

layer {

  name: "pool1"

  type: "Pooling"

  bottom: "conv1"

  top: "pool1"

  pooling_param {

    pool: MAX

    kernel_size: 3

    stride: 2

  }

}

pooling層的運算方法基本是和卷積層是一樣的。

輸入:n*c*w0*h0

輸出:n*c*w1*h1

和卷積層的差別就是其中的c保持不變

 w1=(w0+2*pad-kernel_size)/stride+1;

 h1=(h0+2*pad-kernel_size)/stride+1;

如果設定stride為2,前後兩次卷積部分重疊。

3、Local Response Normalization (LRN)層

此層是對一個輸入的局部區域進行歸一化,達到“側抑制”的效果。可去搜尋AlexNet或GoogLenet,裡面就用到了這個功能

 層類型:LRN

參數:全部為可選,沒有必須

  local_size: 預設為5。如果是跨通道LRN,則表示求和的通道數;如果是在通道内LRN,則表示求和的正方形區域長度。

  alpha: 預設為1,歸一化公式中的參數。

  beta: 預設為5,歸一化公式中的參數。

  norm_region: 預設為ACROSS_CHANNELS。有兩個選擇,ACROSS_CHANNELS表示在相鄰的通道間求和歸一化。WITHIN_CHANNEL表示在一個通道内部特定的區域内進行求和歸一化。與前面的local_size參數對應。

歸一化公式:對于每一個輸入, 去除以,得到歸一化後的輸出

示例:

layers {

  name: "norm1"

  type: LRN

  bottom: "pool1"

  top: "norm1"

  lrn_param {

    local_size: 5

    alpha: 0.0001

    beta: 0.75

  }

}

4、im2col層

如果對matlab比較熟悉的話,就應該知道im2col是什麼意思。它先将一個大矩陣,重疊地劃分為多個子矩陣,對每個子矩陣序列化成向量,最後得到另外一個矩陣。

看一看圖就知道了:

在caffe中,卷積運算就是先對資料進行im2col操作,再進行内積運算(inner product)。這樣做,比原始的卷積操作速度更快。

看看兩種卷積操作的異同:

三.激活層(Activiation Layers)及參數

在激活層中,對輸入資料進行激活操作(實際上就是一種函數變換),是逐元素進行運算的。從bottom得到一個blob資料輸入,運算後,從top輸入一個blob資料。在運算過程中,沒有改變資料的大小,即輸入和輸出的資料大小是相等的。

輸入:n*c*h*w

輸出:n*c*h*w

常用的激活函數有sigmoid, tanh,relu等,下面分别介紹。

1、Sigmoid

對每個輸入資料,利用sigmoid函數執行操作。這種層設定比較簡單,沒有額外的參數。

層類型:Sigmoid

示例:

layer {

  name: "encode1neuron"

  bottom: "encode1"

  top: "encode1neuron"

  type: "Sigmoid"

}

2、ReLU / Rectified-Linear and Leaky-ReLU

ReLU是目前使用最多的激活函數,主要因為其收斂更快,并且能保持同樣效果。

标準的ReLU函數為max(x, 0),當x>0時,輸出x; 當x<=0時,輸出0

f(x)=max(x,0)

層類型:ReLU

可選參數:

negative_slope:預設為0. 對标準的ReLU函數進行變化,如果設定了這個值,那麼資料為負數時,就不再設定為0,而是用原始資料乘以negative_slope

layer {

  name: "relu1"

  type: "ReLU"

  bottom: "pool1"

  top: "pool1"

}

RELU層支援in-place計算,這意味着bottom的輸出和輸入相同以避免記憶體的消耗。

3、TanH / Hyperbolic Tangent

利用雙曲正切函數對資料進行變換。

層類型:TanH

layer {

  name: "layer"

  bottom: "in"

  top: "out"

  type: "TanH"

}

4、Absolute Value

求每個輸入資料的絕對值。

f(x)=Abs(x)

層類型:AbsVal

layer {

  name: "layer"

  bottom: "in"

  top: "out"

  type: "AbsVal"

}

5、Power

對每個輸入資料進行幂運算

f(x)= (shift + scale * x) ^ power

層類型:Power

可選參數:

  power: 預設為1

  scale: 預設為1

  shift: 預設為0

layer {

  name: "layer"

  bottom: "in"

  top: "out"

  type: "Power"

  power_param {

    power: 2

    scale: 1

    shift: 0

  }

}

6、BNLL

binomial normal log likelihood的簡稱

f(x)=log(1 + exp(x))

層類型:BNLL

layer {

  name: "layer"

  bottom: "in"

  top: "out"

  type: “BNLL”

}

四.其它常用層及參數

本文講解一些其它的常用層,包括:softmax_loss層,Inner Product層,accuracy層,reshape層和dropout層及其它們的參數配置。

1、softmax-loss

softmax-loss層和softmax層計算大緻是相同的。softmax是一個分類器,計算的是類别的機率(Likelihood),是Logistic Regression 的一種推廣。Logistic Regression 隻能用于二分類,而softmax可以用于多分類。

softmax與softmax-loss的差別:

softmax計算公式:

而softmax-loss計算公式:

關于兩者的差別更加具體的介紹,可參考:softmax vs. softmax-loss

使用者可能最終目的就是得到各個類别的機率似然值,這個時候就隻需要一個 Softmax層,而不一定要進行softmax-Loss 操作;或者是使用者有通過其他什麼方式已經得到了某種機率似然值,然後要做最大似然估計,此時則隻需要後面的 softmax-Loss 而不需要前面的 Softmax 操作。是以提供兩個不同的 Layer 結構比隻提供一個合在一起的 Softmax-Loss Layer 要靈活許多。

不管是softmax layer還是softmax-loss layer,都是沒有參數的,隻是層類型不同而也

softmax-loss layer:輸出loss值

layer {

  name: "loss"

  type: "SoftmaxWithLoss"

  bottom: "ip1"

  bottom: "label"

  top: "loss"

}

softmax layer: 輸出似然值

layers {

  bottom: "cls3_fc"

  top: "prob"

  name: "prob"

  type: “Softmax"

}

2、Inner Product

全連接配接層,把輸入當作成一個向量,輸出也是一個簡單向量(把輸入資料blobs的width和height全變為1)。

輸入: n*c0*h*w

輸出: n*c1*1*1

全連接配接層實際上也是一種卷積層,隻是它的卷積核大小和原資料大小一緻。是以它的參數基本和卷積層的參數一樣。

層類型:InnerProduct

lr_mult: 學習率的系數,最終的學習率是這個數乘以solver.prototxt配置檔案中的base_lr。如果有兩個lr_mult, 則第一個表示權值的學習率,第二個表示偏置項的學習率。一般偏置項的學習率是權值學習率的兩倍。

必須設定的參數:

    num_output: 過濾器(filfter)的個數

其它參數:

      weight_filler: 權值初始化。 預設為“constant",值全為0,很多時候我們用"xavier"算法來進行初始化,也可以設定為”gaussian"

      bias_filler: 偏置項的初始化。一般設定為"constant",值全為0。

      bias_term: 是否開啟偏置項,預設為true, 開啟

layer {

  name: "ip1"

  type: "InnerProduct"

  bottom: "pool2"

  top: "ip1"

  param {

    lr_mult: 1

  }

  param {

    lr_mult: 2

  }

  inner_product_param {

    num_output: 500

    weight_filler {

      type: "xavier"

    }

    bias_filler {

      type: "constant"

    }

  }

}

3、accuracy

輸出分類(預測)精确度,隻有test階段才有,是以需要加入include參數。

層類型:Accuracy

layer {

  name: "accuracy"

  type: "Accuracy"

  bottom: "ip2"

  bottom: "label"

  top: "accuracy"

  include {

    phase: TEST

  }

}

4、reshape

在不改變資料的情況下,改變輸入的次元。

層類型:Reshape

先來看例子

layer {

    name: "reshape"

    type: "Reshape"

    bottom: "input"

    top: "output"

    reshape_param {

      shape {

        dim: 0  # copy the dimension from below

        dim: 2

        dim: 3

        dim: -1 # infer it from the other dimensions

      }

    }

  }

有一個可選的參數組shape, 用于指定blob資料的各維的值(blob是一個四維的資料:n*c*w*h)。

dim:0  表示次元不變,即輸入和輸出是相同的次元。

dim:2 或 dim:3 将原來的次元變成2或3

dim:-1 表示由系統自動計算次元。資料的總量不變,系統會根據blob資料的其它三維來自動計算目前維的次元值 。

假設原資料為:64*3*28*28, 表示64張3通道的28*28的彩色圖檔

經過reshape變換:

reshape_param {

      shape {

        dim: 0

        dim: 0

        dim: 14

        dim: -1

      }

}

輸出資料為:64*3*14*56

5、Dropout

Dropout是一個防止過拟合的trick。可以随機讓網絡某些隐含層節點的權重不工作。

先看例子:

layer {

  name: "drop7"

  type: "Dropout"

  bottom: "fc7-conv"

  top: "fc7-conv"

  dropout_param {

    dropout_ratio: 0.5

  }

}layer {

  name: "drop7"

  type: "Dropout"

  bottom: "fc7-conv"

  top: "fc7-conv"

  dropout_param {

    dropout_ratio: 0.5

  }

}

隻需要設定一個dropout_ratio就可以了

五.Blob,Layer and Net以及對應配置檔案的編寫

深度網絡(net)是一個組合模型,它由許多互相連接配接的層(layers)組合而成。Caffe就是組建深度網絡的這樣一種工具,它按照一定的政策,一層一層的搭建出自己的模型。它将所有的資訊資料定義為blobs,進而進行便利的操作和通訊。Blob是caffe架構中一種标準的數組,一種統一的記憶體接口,它較長的描述了資訊是如何存儲的,以及如何在層之間通訊的。

1、blob

Blobs封裝了運作時的資料資訊,提供了CPU和GPU的同步。從數學上來說, Blob就是一個N維數組。它是caffe中的資料操作基本機關,就像matlab中以矩陣為基本操作對象一樣。隻是矩陣是二維的,而Blob是N維的。N可以是2,3,4等等。對于圖檔資料來說,Blob可以表示為(N*C*H*W)這樣一個4D數組。其中N表示圖檔的數量,C表示圖檔的通道數,H和W分别表示圖檔的高度和寬度。當然,除了圖檔資料,Blob也可以用于非圖檔資料。比如傳統的多層感覺機,就是比較簡單的全連接配接網絡,用2D的Blob,調用innerProduct層來計算就可以了。

在模型中設定的參數,也是用Blob來表示和運算。它的次元會根據參數的類型不同而不同。比如:在一個卷積層中,輸入一張3通道圖檔,有96個卷積核,每個核大小為11*11,是以這個Blob是96*3*11*11. 而在一個全連接配接層中,假設輸入1024通道圖檔,輸出1000個資料,則Blob為1000*1024

2、layer

層是網絡模型的組成要素和計算的基本機關。層的類型比較多,如Data,Convolution,Pooling,ReLU,Softmax-loss,Accuracy等,一個層的定義大至如下圖:

從bottom進行資料的輸入 ,計算後,通過top進行輸出。圖中的黃色多邊形表示輸入輸出的資料,藍色矩形表示層。

每一種類型的層都定義了三種關鍵的計算:setup,forward and backword

setup: 層的建立和初始化,以及在整個模型中的連接配接初始化。

forward: 從bottom得到輸入資料,進行計算,并将計算結果送到top,進行輸出。

backward: 從層的輸出端top得到資料的梯度,計算目前層的梯度,并将計算結果送到bottom,向前傳遞。

3、Net

就像搭積木一樣,一個net由多個layer組合而成。

現給出 一個簡單的2層神經網絡的模型定義( 加上loss 層就變成三層了),先給出這個網絡的拓撲。

第一層:name為mnist, type為Data,沒有輸入(bottom),隻有兩個輸出(top),一個為data,一個為label

第二層:name為ip,type為InnerProduct, 輸入資料data, 輸出資料ip

第三層:name為loss, type為SoftmaxWithLoss,有兩個輸入,一個為ip,一個為label,有一個輸出loss,沒有畫出來。

對應的配置檔案prototxt就可以這樣寫:

name: "LogReg"

layer {

  name: "mnist"

  type: "Data"

  top: "data"

  top: "label"

  data_param {

    source: "input_leveldb"

    batch_size: 64

  }

}

layer {

  name: "ip"

  type: "InnerProduct"

  bottom: "data"

  top: "ip"

  inner_product_param {

    num_output: 2

  }

}

layer {

  name: "loss"

  type: "SoftmaxWithLoss"

  bottom: "ip"

  bottom: "label"

  top: "loss"

}

第一行将這個模型取名為LogReg, 然後是三個layer的定義,參數都比較簡單,隻列出必須的參數。

六.Solver及其配置

solver算是caffe的核心的核心,它協調着整個模型的運作。caffe程式運作必帶的一個參數就是solver配置檔案。運作代碼一般為

# caffe train --solver=*_slover.prototxt

在Deep Learning中,往往loss function是非凸的,沒有解析解,我們需要通過優化方法來求解。solver的主要作用就是交替調用前向(forward)算法和後向(backward)算法來更新參數,進而最小化loss,實際上就是一種疊代的優化算法。

到目前的版本,caffe提供了六種優化算法來求解最優參數,在solver配置檔案中,通過設定type類型來選擇。

Stochastic Gradient Descent (type: "SGD"),

AdaDelta (type: "AdaDelta"),

Adaptive Gradient (type: "AdaGrad"),

Adam (type: "Adam"),

Nesterov’s Accelerated Gradient (type: "Nesterov") and

RMSprop (type: "RMSProp")

  具體的每種方法的介紹,請看本系列的下一篇文章, 本文着重介紹solver配置檔案的編寫。

Solver的流程:

1.設計好需要優化的對象,以及用于學習的訓練網絡和用于評估的測試網絡。(通過調用另外一個配置檔案prototxt來進行)

2.通過forward和backward疊代的進行優化來跟新參數。

3.定期的評價測試網絡。(可設定多少次訓練後,進行一次測試)

4.在優化過程中顯示模型和solver的狀态

在每一次的疊代過程中,solver做了這幾步工作:

1、調用forward算法來計算最終的輸出值,以及對應的loss

2、調用backward算法來計算每層的梯度

3、根據選用的slover方法,利用梯度進行參數更新

4、記錄并儲存每次疊代的學習率、快照,以及對應的狀态。

接下來,我們先來看一個執行個體:

net: "examples/mnist/lenet_train_test.prototxt"

test_iter: 100

test_interval: 500

base_lr: 0.01

momentum: 0.9

type: SGD

weight_decay: 0.0005

lr_policy: "inv"

gamma: 0.0001

power: 0.75

display: 100

max_iter: 20000

snapshot: 5000

snapshot_prefix: "examples/mnist/lenet"

solver_mode: CPU

接下來,我們對每一行進行詳細解譯:

net: "examples/mnist/lenet_train_test.prototxt"

設定深度網絡模型。每一個模型就是一個net,需要在一個專門的配置檔案中對net進行配置,每個net由許多的layer所組成。每一個layer的具體配置方式可參考本系列文文章中的(2)-(5)。注意的是:檔案的路徑要從caffe的根目錄開始,其它的所有配置都是這樣。

也可用train_net和test_net來對訓練模型和測試模型分别設定。例如:

train_net: "examples/hdf5_classification/logreg_auto_train.prototxt"

test_net: "examples/hdf5_classification/logreg_auto_test.prototxt"

接下來第二行:

test_iter: 100

這個要與test layer中的batch_size結合起來了解。mnist資料中測試樣本總數為10000,一次性執行全部資料效率很低,是以我們将測試資料分成幾個批次來執行,每個批次的數量就是batch_size。假設我們設定batch_size為100,則需要疊代100次才能将10000個資料全部執行完。是以test_iter設定為100。執行完一次全部資料,稱之為一個epoch

test_interval: 500

測試間隔。也就是每訓練500次,才進行一次測試。

base_lr: 0.01

lr_policy: "inv"

gamma: 0.0001

power: 0.75

這四行可以放在一起了解,用于學習率的設定。隻要是梯度下降法來求解優化,都會有一個學習率,也叫步長。base_lr用于設定基礎學習率,在疊代的過程中,可以對基礎學習率進行調整。怎麼樣進行調整,就是調整的政策,由lr_policy來設定。

lr_policy可以設定為下面這些值,相應的學習率的計算為:

- fixed:保持base_lr不變.

- step: 如果設定為step,則還需要設定一個stepsize,  傳回

      base_lr * gamma ^ (floor(iter / stepsize)),其中iter表示目前的疊代次數

- exp: 傳回base_lr * gamma ^ iter, iter為目前疊代次數

- inv:如果設定為inv,還需要設定一個power, 傳回base_lr * (1 + gamma * iter) ^ (- power)

- multistep: 如果設定為multistep,則還需要設定一個stepvalue。這個參數和step很相似,step是均勻等間隔變化,而multistep則是根據 stepvalue值變化

- poly:學習率進行多項式誤差, 傳回 base_lr (1 - iter/max_iter) ^ (power)

- sigmoid:學習率進行sigmod衰減,傳回 base_lr ( 1/(1 + exp(-gamma * (iter - stepsize))))

multistep示例:

base_lr: 0.01

momentum: 0.9

weight_decay: 0.0005

# The learning rate policy

lr_policy: "multistep"

gamma: 0.9

stepvalue: 5000

stepvalue: 7000

stepvalue: 8000

stepvalue: 9000

stepvalue: 9500

接下來的參數:

momentum :0.9

上一次梯度更新的權重,具體可參看下一篇文章。

type: SGD

優化算法選擇。這一行可以省掉,因為預設值就是SGD。總共有六種方法可選擇,在本文的開頭已介紹。

weight_decay: 0.0005

權重衰減項,防止過拟合的一個參數

display: 100

每訓練100次,在螢幕上顯示一次。如果設定為0,則不顯示。

max_iter: 20000

最大疊代次數。這個數設定太小,會導緻沒有收斂,精确度很低。設定太大,會導緻震蕩,浪費時間。

snapshot: 5000

snapshot_prefix: "examples/mnist/lenet"

快照。将訓練出來的model和solver狀态進行儲存,snapshot用于設定訓練多少次後進行儲存,預設為0,不儲存。snapshot_prefix設定儲存路徑。

還可以設定snapshot_diff,是否儲存梯度值,預設為false,不儲存。

也可以設定snapshot_format,儲存的類型。有兩種選擇:HDF5 和BINARYPROTO ,預設為BINARYPROTO

solver_mode: CPU

設定運作模式。預設為GPU,如果你沒有GPU,則需要改成CPU,否則會出錯。

 注意:以上的所有參數都是可選參數,都有預設值。根據solver方法(type)的不同,還有一些其它的參數,在此不一一列舉。

七.Solver優化方法

上文提到,到目前為止,caffe總共提供了六種優化方法:

Stochastic Gradient Descent (type: "SGD"),

AdaDelta (type: "AdaDelta"),

Adaptive Gradient (type: "AdaGrad"),

Adam (type: "Adam"),

Nesterov’s Accelerated Gradient (type: "Nesterov") and

RMSprop (type: "RMSProp")

Solver就是用來使loss最小化的優化方法。對于一個資料集D,需要優化的目标函數是整個資料集中所有資料loss的平均值。

其中,fW(x(i))計算的是資料x(i)上的loss, 先将每個單獨的樣本x的loss求出來,然後求和,最後求均值。 r(W)是正則項(weight_decay),為了減弱過拟合現象。

如果采用這種Loss 函數,疊代一次需要計算整個資料集,在資料集非常大的這情況下,這種方法的效率很低,這個也是我們熟知的梯度下降采用的方法。

在實際中,通過将整個資料集分成幾批(batches), 每一批就是一個mini-batch,其數量(batch_size)為N<<|D|,此時的loss 函數為:

有了loss函數後,就可以疊代的求解loss和梯度來優化這個問題。在神經網絡中,用forward pass來求解loss,用backward pass來求解梯度。

在caffe中,預設采用的Stochastic Gradient Descent(SGD)進行優化求解。後面幾種方法也是基于梯度的優化方法(like SGD),是以本文隻介紹一下SGD。其它的方法,有興趣的同學,可以去看文獻原文。

1、Stochastic gradient descent(SGD)

随機梯度下降(Stochastic gradient descent)是在梯度下降法(gradient descent)的基礎上發展起來的,梯度下降法也叫最速下降法,具體原理在網易公開課《機器學習》中,吳恩達教授已經講解得非常詳細。SGD在通過負梯度和上一次的權重更新值Vt的線性組合來更新W,疊代公式如下:

其中,  是負梯度的學習率(base_lr),是上一次梯度值的權重(momentum),用來權重之前梯度方向對現在梯度下降方向的影響。這兩個參數需要通過tuning來得到最好的結果,一般是根據經驗設定的。如果你不知道如何設定這些參數,可以參考相關的論文。

在深度學習中使用SGD,比較好的初始化參數的政策是把學習率設為0.01左右(base_lr: 0.01),在訓練的過程中,如果loss開始出現穩定水準時,對學習率乘以一個常數因子(gamma),這樣的過程重複多次。

對于momentum,一般取值在0.5--0.99之間。通常設為0.9,momentum可以讓使用SGD的深度學習方法更加穩定以及快速。

關于更多的momentum,請參看Hinton的《A Practical Guide to Training Restricted Boltzmann Machines》。  

執行個體: 

base_lr: 0.01

lr_policy: "step"

gamma: 0.1   

stepsize: 1000  

max_iter: 3500

momentum: 0.9

lr_policy設定為step,則學習率的變化規則為 base_lr * gamma ^ (floor(iter / stepsize))

即前1000次疊代,學習率為0.01; 第1001-2000次疊代,學習率為0.001; 第2001-3000次疊代,學習率為0.00001,第3001-3500次疊代,學習率為10-5  

上面的設定隻能作為一種指導,它們不能保證在任何情況下都能得到最佳的結果,有時候這種方法甚至不work。如果學習的時候出現diverge(比如,你一開始就發現非常大或者NaN或者inf的loss值或者輸出),此時你需要降低base_lr的值(比如,0.001),然後重新訓練,這樣的過程重複幾次直到你找到可以work的base_lr。

2、AdaDelta

AdaDelta是一種”魯棒的學習率方法“,是基于梯度的優化方法(like SGD)。

具體的介紹文獻:

M. Zeiler ADADELTA: AN ADAPTIVE LEARNING RATE METHOD. arXiv preprint, 2012.

示例:

net: "examples/mnist/lenet_train_test.prototxt"

test_iter: 100

test_interval: 500

base_lr: 1.0

lr_policy: "fixed"

momentum: 0.95

weight_decay: 0.0005

display: 100

max_iter: 10000

snapshot: 5000

snapshot_prefix: "examples/mnist/lenet_adadelta"

solver_mode: GPU

type: "AdaDelta"

delta: 1e-6

從最後兩行可看出,設定solver type為Adadelta時,需要設定delta的值。

3、AdaGrad

自适應梯度(adaptive gradient)是基于梯度的優化方法(like SGD)

具體的介紹文獻:

Duchi, E. Hazan, and Y. Singer. Adaptive Subgradient Methods for Online Learning and Stochastic Optimization. The Journal of Machine Learning Research, 2011.

示例:

net: "examples/mnist/mnist_autoencoder.prototxt"

test_state: { stage: 'test-on-train' }

test_iter: 500

test_state: { stage: 'test-on-test' }

test_iter: 100

test_interval: 500

test_compute_loss: true

base_lr: 0.01

lr_policy: "fixed"

display: 100

max_iter: 65000

weight_decay: 0.0005

snapshot: 10000

snapshot_prefix: "examples/mnist/mnist_autoencoder_adagrad_train"

# solver mode: CPU or GPU

solver_mode: GPU

type: "AdaGrad"

4、Adam

是一種基于梯度的優化方法(like SGD)。

 具體的介紹文獻:

D. Kingma, J. Ba. Adam: A Method for Stochastic Optimization. International Conference for Learning Representations, 2015.

5、NAG

Nesterov 的加速梯度法(Nesterov’s accelerated gradient)作為凸優化中最理想的方法,其收斂速度非常快。

 具體的介紹文獻:

 I. Sutskever, J. Martens, G. Dahl, and G. Hinton. On the Importance of Initialization and Momentum in Deep Learning. Proceedings of the 30th International Conference on Machine Learning, 2013.

示例:

net: "examples/mnist/mnist_autoencoder.prototxt"

test_state: { stage: 'test-on-train' }

test_iter: 500

test_state: { stage: 'test-on-test' }

test_iter: 100

test_interval: 500

test_compute_loss: true

base_lr: 0.01

lr_policy: "step"

gamma: 0.1

stepsize: 10000

display: 100

max_iter: 65000

weight_decay: 0.0005

snapshot: 10000

snapshot_prefix: "examples/mnist/mnist_autoencoder_nesterov_train"

momentum: 0.95

# solver mode: CPU or GPU

solver_mode: GPU

type: "Nesterov"

6、RMSprop

RMSprop是Tieleman在一次 Coursera課程演講中提出來的,也是一種基于梯度的優化方法(like SGD)

具體的介紹文獻:

T. Tieleman, and G. Hinton. RMSProp: Divide the gradient by a running average of its recent magnitude. COURSERA: Neural Networks for Machine Learning.Technical report, 2012.

 示例:

net: "examples/mnist/lenet_train_test.prototxt"

test_iter: 100

test_interval: 500

base_lr: 1.0

lr_policy: "fixed"

momentum: 0.95

weight_decay: 0.0005

display: 100

max_iter: 10000

snapshot: 5000

snapshot_prefix: "examples/mnist/lenet_adadelta"

solver_mode: GPU

type: "RMSProp"

rms_decay: 0.98

最後兩行,需要設定rms_decay值。

八.指令行解析

caffe的運作提供三種接口:c++接口(指令行)、Python接口和matlab接口。本文先對指令行進行解析,後續會依次介紹其它兩個接口。

caffe的c++主程式(caffe.cpp)放在根目錄下的tools檔案夾内, 當然還有一些其它的功能檔案,如:convert_imageset.cpp, train_net.cpp, test_net.cpp等也放在這個檔案夾内。經過編譯後,這些檔案都被編譯成了可執行檔案,放在了 ./build/tools/ 檔案夾内。是以我們要執行caffe程式,都需要加 ./build/tools/ 字首。

如:

# sudo sh ./build/tools/caffe train --solver=examples/mnist/train_lenet.sh

caffe程式的指令行執行格式如下:

caffe <command> <args>

其中的<command>有這樣四種:

train

test

device_query

time

對應的功能為:

train----訓練或finetune模型(model),

test-----測試模型

device_query---顯示gpu資訊

time-----顯示程式執行時間

其中的<args>參數有:

-solver

-gpu

-snapshot

-weights

-iteration

-model

-sighup_effect

-sigint_effect

注意前面有個-符号。對應的功能為:

-solver:必選參數。一個protocol buffer類型的檔案,即模型的配置檔案。如:

# ./build/tools/caffe train -solver examples/mnist/lenet_solver.prototxt

-gpu: 可選參數。該參數用來指定用哪一塊gpu運作,根據gpu的id進行選擇,如果設定為'-gpu all'則使用所有的gpu運作。如使用第二塊gpu運作:

# ./build/tools/caffe train -solver examples/mnist/lenet_solver.prototxt -gpu 2

-snapshot:可選參數。該參數用來從快照(snapshot)中恢複訓練。可以在solver配置檔案設定快照,儲存solverstate。如:

# ./build/tools/caffe train -solver examples/mnist/lenet_solver.prototxt -snapshot examples/mnist/lenet_iter_5000.solverstate

-weights:可選參數。用預先訓練好的權重來fine-tuning模型,需要一個caffemodel,不能和-snapshot同時使用。如:

# ./build/tools/caffe train -solver examples/finetuning_on_flickr_style/solver.prototxt -weights models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel

-iterations: 可選參數,疊代次數,預設為50。 如果在配置檔案檔案中沒有設定疊代次數,則預設疊代50次。

-model:可選參數,定義在protocol buffer檔案中的模型。也可以在solver配置檔案中指定。

-sighup_effect:可選參數。用來設定當程式發生挂起事件時,執行的操作,可以設定為snapshot, stop或none, 預設為snapshot

-sigint_effect: 可選參數。用來設定當程式發生鍵盤中止事件時(ctrl+c), 執行的操作,可以設定為snapshot, stop或none, 預設為stop

剛才舉例了一些train參數的例子,現在我們來看看其它三個<command>:

test參數用在測試階段,用于最終結果的輸出,要模型配置檔案中我們可以設定需要輸入accuracy還是loss. 假設我們要在驗證集中驗證已經訓練好的模型,就可以這樣寫

# ./build/tools/caffe test -model examples/mnist/lenet_train_test.prototxt -weights examples/mnist/lenet_iter_10000.caffemodel -gpu 0 -iterations 100

這個例子比較長,不僅用到了test參數,還用到了-model, -weights, -gpu和-iteration四個參數。意思是利用訓練好了的權重(-weight),輸入到測試模型中(-model),用編号為0的gpu(-gpu)測試100次(-iteration)。

time參數用來在螢幕上顯示程式運作時間。如:

# ./build/tools/caffe time -model examples/mnist/lenet_train_test.prototxt -iterations 10

這個例子用來在螢幕上顯示lenet模型疊代10次所使用的時間。包括每次疊代的forward和backward所用的時間,也包括每層forward和backward所用的平均時間。

# ./build/tools/caffe time -model examples/mnist/lenet_train_test.prototxt -gpu 0

這個例子用來在螢幕上顯示lenet模型用gpu疊代50次所使用的時間。

# ./build/tools/caffe time -model examples/mnist/lenet_train_test.prototxt -weights examples/mnist/lenet_iter_10000.caffemodel -gpu 0 -iterations 10

利用給定的權重,利用第一塊gpu,疊代10次lenet模型所用的時間。

device_query參數用來診斷gpu資訊。

# ./build/tools/caffe device_query -gpu 0

最後,我們來看兩個關于gpu的例子

# ./build/tools/caffe train -solver examples/mnist/lenet_solver.prototxt -gpu 0,1

# ./build/tools/caffe train -solver examples/mnist/lenet_solver.prototxt -gpu all

這兩個例子表示: 用兩塊或多塊GPU來平行運算,這樣速度會快很多。但是如果你隻有一塊或沒有gpu, 就不要加-gpu參數了,加了反而慢。

最後,在linux下,本身就有一個time指令,是以可以結合進來使用,是以我們運作mnist例子的最終指令是(一塊gpu):

$ sudo time ./build/toos/caffe train -solver examples/mnist/lenet_solver.prototxt

轉載于:https://www.cnblogs.com/invisible2/p/10371195.html