之前用deploy.prototxt 還原train_val.prototxt過程中,遇到了坑,所以打算總結一下
本人以熟悉的LeNet網絡結構為例子
不同點主要在一前一后,相同點都在中間
train_val.prototxt 中的開頭
看這個名字也知道,里面定義的是訓練和驗證時候的網絡,所以在開始的時候要定義訓練集和驗證集的來源
name: "LeNet"
layer {
name: "mnist"
type: "Data"
top: "data"
top: "label"
include {
phase: TRAIN
}
transform_param {
scale: 0.00390625
}
data_param {
# 這里定義了之前將數據集轉成lmdb數據格式的文件位置
source: "examples/mnist/mnist_train_lmdb"
# 這個定義了一次行送入網絡的圖像個數
batch_size: 64
backend: LMDB
}
}
layer {
name: "mnist"
type: "Data"
top: "data"
top: "label"
include {
phase: TEST
}
transform_param {
scale: 0.00390625
}
data_param {
# 這里定義了驗證集的數據來源
source: "examples/mnist/mnist_test_lmdb"
batch_size: 100
backend: LMDB
}
}
deploy.prototxt 中的開頭
看這個名字也知道,這個配置文件適用於部署,也就是用於實際場景時候的配置文件,所以開始的時候不必在定義數據集的來源,但是需要定義輸入數據的大小格式。
name: "LeNet"
layer {
name: "data"
type: "Input"
top: "data"
# 輸入數據的batch size, channel, width, height
input_param { shape: { dim: 64 dim: 1 dim: 28 dim: 28 } }
}
train_val.prototxt 中的結尾
如果是一般的卷積網絡的話,最后面都是用一個全連接,將feature map 轉成固定長度的向量,然后輸出種類的個數。所以在最后的時候,需要說明輸出種類的個數。
layer {
name: "ip2"
type: "InnerProduct"
bottom: "ip1"
top: "ip2"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
inner_product_param {
# 在這里定義了輸出種類的個數
num_output: 10
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
因為這里面包含了驗證的部分,驗證的時候,需要輸出結果的准確率,所以需要定義准確率的輸出。
layer {
name: "accuracy"
type: "Accuracy"
bottom: "ip2"
bottom: "label"
top: "accuracy"
include {
phase: TEST
}
}
最后還有一個不同就是,因為是訓練模型,所以包括forward和backward,所以最后需要定義一個損失函數。這里用的是SoftmaxWithLoss,而在deploy.prototxt,因為只有forward,所以定義的是Softmax,也就是分類器。
layer {
name: "loss"
# 定義的是損失函數
type: "SoftmaxWithLoss"
bottom: "ip2"
bottom: "label"
top: "loss"
}
deploy.prototxt 中的最后
這里定義了Softmax分類器,輸出最后各類的概率值。
layer {
name: "prob"
# 定義的是分類器
type: "Softmax"
bottom: "ip2"
top: "prob"
}
train_val.prototxt 和 deploy.prototxt中間部分
兩個的中間部分都是一樣的,定義了一些卷積、激活、池化、Dropout、LRN(local response normalization)、全連接等操作。
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"
}
}
}
layer {
name: "pool1"
type: "Pooling"
bottom: "conv1"
top: "pool1"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "conv2"
type: "Convolution"
bottom: "pool1"
top: "conv2"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
convolution_param {
num_output: 50
kernel_size: 5
stride: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "pool2"
type: "Pooling"
bottom: "conv2"
top: "pool2"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
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"
}
}
}
layer {
name: "relu1"
type: "ReLU"
bottom: "ip1"
top: "ip1"
}
layer {
name: "ip2"
type: "InnerProduct"
bottom: "ip1"
top: "ip2"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
inner_product_param {
num_output: 10
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}