本文以OpenPose的网络结构为例对各层参数进行解析
训练的网络文件
数据层
layer {
name: "data" 表示该层名字
type: "CPMData" 层有多种类型,比如:Data、Convolution、Pooling,Data表示数据来源于Leveldb或者LMDB
top: "data" 每一层用top来输出数据,只有top没有bottom,则这一层只有输出没有输入,反之亦然
top: "label" 如果有多个top和bottom,表示有多个blobs数据的输入输出
data_param {
source: "/mnt/sdb/yangbin/COCO_kpt/lmdb" 包含数据库的目录名称
batch_size: 10 每次处理数据的个数
backend: LMDB 选择采用Leveldb还是LMDB,默认采用leveldb
}
cpm_transform_param { 自定义层,之后会进行补充
stride: 8
max_rotate_degree: 40
visualize: false
crop_size_x: 368
crop_size_y: 368
scale_prob: 1
scale_min: 0.5
scale_max: 1.1
target_dist: 0.6
center_perterb_max: 40
do_clahe: false
num_parts: 56
np_in_lmdb: 17
}
}
Eltwise层
layer {
name: "weight_stage1_L2" 官方注释:http://caffe.berkeleyvision.org/tutorial/layers/eltwise.html
type: "Eltwise" 按元素操作层
bottom: "conv5_5_CPM_L2"
bottom: "heat_weight"
top: "weight_stage1_L2"
eltwise_param {
operation: PROD 支持三种基本操作:1.PROD - 按元素乘积; 2.SUM - 按元素求和(默认,若实现相减,设置第一个coeff参数为1,第二个coeff参数为-1); 3.MAX - 保存元素大者
}
}
EuclideanLoss层
layer {
name: "loss_stage1_L1" 官方注释:http://caffe.berkeleyvision.org/tutorial/layers/euclideanloss.html
type: "EuclideanLoss" 源码分析:https://blog.csdn.net/seashell_9/article/details/68064294
bottom: "weight_stage1_L1"
bottom: "label_vec"
top: "loss_stage1_L1"
loss_weight: 1 默认为1
}
BatchNorm层
BN层的设定一般按照conv→BN→scale→relu的顺序来形成一个block
https://www.cnblogs.com/makefile/p/batch-norm.html?utm_source=debugrun&utm_medium=referral
layer {
name: "conv1/bn"
type: "BatchNorm"
bottom: "conv1"
top: "conv1" #inplace
param { #均值
lr_mult: 0
decay_mult: 0
}
param {
lr_mult: 0 #方差
decay_mult: 0
}
param {
lr_mult: 0 #Scale
decay_mult: 0
}
batch_norm_param {
use_global_stats: true #训练的时候要设置为false,测试时设置为true
eps: 1e-5 #分母附加值,防止除以方差时出现除0操作,默认为1e-5
}
}
VGG19前十层
OpenPose采用VGG19模型的前十层网络进行初始化
卷积层
layer {
name: "conv1_1" #表示该层的名称
type: "Convolution" #层类型
bottom: "image" #输入
top: "conv1_1" #输出
param {
lr_mult: 1.0 #权值的学习率,最终的学习率是这个系数乘以solver.prototxt配置文件中的base_Ir
decay_mult: 1 #权值衰减系数
}
param {
lr_mult: 2.0 #如果有两个Ir_mult,则第二个代表偏置项的学习率,一般来说偏置项的学习率是权值学习率的两倍
decay_mult: 0
}
convolution_param {
num_output: 64 #卷积核的个数,convolution_param主要用于设定卷积层的特有参数
pad: 1
kernel_size: 3
weight_filler { #权值初始化
type: "gaussian" #默认为“constant”,值为0,“gaussian”使用高斯分布初始化权值
std: 0.01 #std是参数初始化成是高斯分布的标准差,std越小,证明高斯曲线越平滑,各个权重值基本相同
详见https://blog.csdn.net/kenny_star/article/details/69949846
}
bias_filler {
type: "constant" #偏置项的初始化,一般设置为“constant”,值全为0
}
}
}
激活层
layer {
name: "relu1_1" 对输入数据进行激活操作(一种函数变换),从bottom得到一个blob数据输入,运算后,从top输出一个blob数据
type: "ReLU" 在运算过程中,只对输入数据逐个元素进行函数变化,不改变数据维度大小
bottom: "conv1_1" 输入:n*c*h*w 输出:n*c*h*w
top: "conv1_1" Relu层支持in-place计算,因此Relu层的输入输出可以相同,这意味着该层的输入输出可以共享同一块内存,减少内存消耗,其它层不支持
}
池化层
layer {
name: "pool1_stage1"
type: "Pooling" #层类型
bottom: "conv1_2"
top: "pool1_stage1"
pooling_param {
pool: MAX #池化方法,默认为MAX,其他还有AVE、STOCHASTIC(随机采样池化)
kernel_size: 2
stride: 2
}
}
连接层
layer {
name: "concat_stage2" #输入:n_i * c_i * h * w for each input blob i from 1 to K.
type: "Concat"
bottom: "conv5_5_CPM_L1"
bottom: "conv5_5_CPM_L2"
bottom: "conv4_4_CPM"
top: "concat_stage2"
concat_param { https://blog.csdn.net/u012426298/article/details/80743284
axis: 1 if axis = 0: (n_1 + n_2 + ... + n_K) * c_1 * h * w, and all input c_i should be the same
if axis = 1: n_1 * (c_1 + c_2 + ... + c_K) * h * w, and all input n_i should be the same
}
}
Scale层
https://blog.csdn.net/zxyhhjs2017/article/details/85265921