caffe 網路模型檔案中的引數含義(top bottom lr_mult decay_mult)與模型編寫以及模型自定義
文章目錄
__net.prototxt
(網路模型線上視覺化工具)[http://ethereon.github.io/netscope/#/editor]
基本概念
layer{ name: "" type: "Data、Scale、Convolution、ReLU、Pooling、 Eltwise 、InnerProduct、Accuracy、Softmax、Python" bottom: "data" top: "sub_mean" }
基本引數說明 這些引數基本每一層都有
name 根據網路總的位置可自定義一個相關的名字
type Convolution caffe內建的卷積層
bottle 前一層的輸入
top 這一層的輸出
param 設定通用引數
lr_mult 學習率係數, 最終學習率是lr_multsolver.prototxt配置檔案中的base_lr
decay_mult 權值衰減 最終權值衰減decay_multsolver.prototxt的weight_dacay
所以權值更新wi = wi -(base_lr * lr_mult) *dwi - (weight_dacay * decay_mult) * wi
(dwi是誤差關於wi的偏導數)
如果有兩個lr_mult, 則第一個表示權值的學習率,第二個表示偏置項的學習率。
lr_mult、decay_mult僅在有引數的層出現,比如卷積層、全連線層
資料層
Convolution Layer
- 基本結構
layer { name: "conv1" type: "Convolution" bottom: "sub_mean" top: "conv1" param { lr_mult: 1.0 decay_mult: 1.0 } param { lr_mult: 1.0 decay_mult: 0.0 } convolution_param { num_output: 64 bias_term: true kernel_size: 7 stride: 2 weight_filler { type: "xavier" } } }
引數說明
name 根據網路總的位置可自定義一個相關的名字
type Convolution caffe內建的卷積層
bottle 前一層的輸入
top 這一層的輸出
param 設定通用引數
lr_mult 學習率係數, 最終學習率是lr_multsolver.prototxt配置檔案中的base_lr
decay_mult 權值衰減 最終權值衰減decay_multsolver.prototxt的weight_dacay
所以權值更新wi = wi -(base_lr * lr_mult) *dwi - (weight_dacay * decay_mult) * wi
(dwi是誤差關於wi的偏導數)
如果有兩個lr_mult, 則第一個表示權值的學習率,第二個表示偏置項的學習率。
convolution_param 設定卷集層特有引數
num_output 卷積核的個數 【生成特徵圖的個數】
kernel_size 卷積核的大小
stride 卷積核的步長,預設為1
pad 擴充邊緣,預設為0,不擴充 (比如卷積核的大小為55,那麼pad設定為2,則四個邊緣都擴充2個畫素,即寬度和高度都擴充了4個畫素,如果步長為1的話,這樣卷積運算之後的特徵圖就不會變小)
bias_term: true 是否開啟偏置項,預設為true, 開啟
bias_filler: 偏置項的初始化。一般設定為"constant",值全為0。
weight_filler 權值初始化的演算法方式 預設為“constant",值全為0,很多時候我們用"xavier"演算法來進行初始化,也可以設定為”gaussian"
例如
輸入:n×C0×w0×h0
輸出:n×C1×w1×h1
其中,c1就是引數中的num_output,生成的特徵圖個數
w1=(w0+2pad-kernel_size)/stride+1;
h1=(h0+2*pad-kernel_size)/stride+1;
如果設定stride為1,前後兩次卷積部分存在重疊。如果設定pad=(kernel_size-1)/2,則運算後,寬度和高度不變
Deconvolution 反捲積層
layer {
type: "Deconvolution"
name: 'upsample_8'
bottom: 'score-dsn4'
top: 'score-dsn4-up'
param { lr_mult: 0 decay_mult: 1 }
param { lr_mult: 0 decay_mult: 0}
convolution_param { kernel_size: 16 stride: 8 num_output: 1 } }
卷積和反捲積的引數結構完全一樣,就是計算輸出的方式不太一樣
convolution: output = (input + 2 * pads - kernal_size) / stride + 1;
deconvolution: output = (input - 1) * stride + kernal_size - 2 * pads
Batch Normalization 層
作用: 提出採用 Batch Normalization 來對 ICS( Internal Covariate Shift) 進行消除,加速網路訓練. 其主要是採用 normalization 處理來固定網路層輸入的均值和方差(means and variances).
- 減少了網路的梯度計算對於引數 scale 和初始值的依賴
- 允許使用更大的 learning rates,而不出現發散
- 具有對模型的正則作用
- 能減少對 Dropout 的使用
- 能避免網路進入飽和狀態進而利用網路的飽和非線性
在哪用
- BN 層有助於網路訓練,但在 inference 階段則是不必要的,網路輸出只與輸入相關,Inference 階段均值和方差是固定的
- BN層可以應用於網路的任何地方
caffe 實現
src/caffe /layer/batch_norm_layer.cpp
src/caffe /layer/batch_norm_layer.cu
src/caffe /layer/scale_layer.cpp
src/caffe /layer/scale_layer.cu
Batch Normalization主要做兩部分:
- 對輸入進行歸一化 —— 對應 Caffe BatchNorm 層
- 歸一化再 平移縮放 y=γ⋅xnorm+β —— 對應 Caffe Scale 層
## 以 resnet中的基本結構為例
layer {
name: "first_conv"
type: "Convolution"
bottom: "data"
top: "first_conv"
param {
lr_mult: 1
decay_mult: 1
}
convolution_param {
num_output: 16
pad: 1
kernel_size: 3
stride: 1
weight_filler {
type: "msra"
}
}
}
layer {
name: "first_conv_bn"
type: "BatchNorm"
bottom: "first_conv"
top: "first_conv"
param {
lr_mult: 0
decay_mult: 0
}
param {
lr_mult: 0
decay_mult: 0
}
param {
lr_mult: 0
decay_mult: 0
}
}
layer {
name: "first_conv_scale"
type: "Scale"
bottom: "first_conv"
top: "first_conv"
scale_param {
bias_term: true
}
}
layer {
name: "first_conv_relu"
type: "ReLU"
bottom: "first_conv"
top: "first_conv"
}
Polling Layer
layer {
name: "pool1"
type: "Pooling"
bottom: "conv1"
top: "pool1"
pooling_param {
pool: MAX
kernel_size: 3
stride: 2
}
}
池化層 為了減少運算量和資料維度的層
pooling_param引數設定
pool 池化方法 預設MAX 還有 AVE、STOCHASTIC
kernel_size 池化的核大小
stride 池化的步長,預設為1,一般設定為2
pad 邊緣擴充,預設為0
pooling層的運算方法基本是和卷積層是一樣的。輸入:ncw0h0
輸出:ncw1h1
和卷積層的區別就是其中的c保持不變
w1=(w0+2pad-kernel_size)/stride+1;
h1=(h0+2pad-kernel_size)/stride+1;
如果設定stride為2,前後兩次卷積部分不重疊。100100的特徵圖池化後,變成5050.
crop層 裁剪
layer {
type: "Crop"
name: 'crop'
bottom: 'score-dsn4-up'
bottom: 'data'
top: 'upscore-dsn4'
}
Caffe中的資料是以 blobs形式存在的,blob是四維資料,即 (Batch size, number of Chennels, Height, Width)=(N, C, H, W) —(0,1,2,3)
Crop 的輸入層 bottom blobs有兩個,輸出層有一個 top bottom
- 前一個是要進行裁剪的bottom
- 後一個是參考輸入
- 輸出層與第二個輸入結構相同
crop_param
{
axis: default = 2
offset :
}
全連線層 fc 、以及最後一級全連線後的結構
layer {
name: "fc3"
type: "InnerProduct"
bottom: "pool_avg"
top: "fc3"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 1.0
decay_mult: 0.0
}
inner_product_param {
num_output: 3
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0.0
}
}
}
inner_product_param 全連線層引數設定
num_output 全連線神經元數目
weight_filler 權值初始化方式
bias_filler 偏置項初始化方式
在caffe中,最後一級全連線後面會跟有如下三種情況
- loss function 做優化學習,用於反向傳播(train-data)
- Accuracy Layer 驗證當前模型引數的準確率(validation-data)
- softmax function 做部署推理用(輸出類別的概率)
但是有幾點需要說明:
1、caffe在計算Accuravy時,利用的是最後一個全連結層的輸出(而不帶有acitvation function)?
因為計算accuracy應該使用計算得到的labels與資料集真正的labels去做計算,為什麼caffe的accuracy要將fc3接入Accuray層呢?
原來,在AccuracyLayer內部,實現了“利用fc8的輸出得到資料集的預測labels”(數值最大的那個值得idnex就是樣本的類別),那麼,再與輸入的資料集真實lebels作對比,就實現了accuray的計算.
所以,如果僅僅是做預測,利用f3的輸出就夠了(輸出值最大的那個位置即為輸入的label),該輸出表示了輸入的樣本屬於每一類的可能性大小,但並不是概率值;
如果為了使輸出具有統計意義,需要加入softmax function,它只是使前面的全連線層的輸出(fc3)具有了概率意義,並不改變這些輸出之前的大小關係,因為softmax function本身就是增函式;
為了利用誤差反向傳播,還需要構造loss function
在caffe 根據訓練和部署的不同,最後一層全連線層通常
layer {
name: "cee_loss"
type: "Python"
bottom: "fc3"
bottom: "label"
top: "cee_loss"
python_param {
module: "digits_python_layers"
layer: "CrossEntropySoftmaxWithEntropyLossLayer"
param_str: "{ 'entScale': 0.01, 'pScale': 0.0001, 'label_eps': 0.01 }"
}
loss_weight: 1
exclude {
stage: "deploy"
}
}
layer {
name: "softmax"
type: "Softmax"
bottom: "fc3"
top: "softmax"
include {
stage: "deploy"
}
}
layer {
name: "accuracy"
type: "Accuracy"
bottom: "fc3"
bottom: "label"
top: "accuracy"
include {
stage: "val"
}
}