本文应用resnet对同一批行人数据做性别和年龄的这两种属性的分类。由于resnet网络的输入数据为图像,故不需要生成lmdb文件。具体实现方法参考了caffe实现多label输入(修改源码版) 1。
本文意在作为学习笔记,方便日后查阅,并具有实际可操作性,给后面的学习者提供一些指导。
步骤如下
一、Resnet文件夹下的caffe文件夹里修改caffe源代码
二、编译caffe
三、修改MS_train.prototxt文件
四、训练网络
下面具体介绍:
一、caffe源码的修改
如参考文献 1 里所示,需要注意的是我的IDNumber设成了13。
二、caffe编译
可能是由于版本号的问题,这里不用cmake编译。
在caffe文件夹下执行命令:
make all -j8
若出现
nothing to be done for 'all'
说明已经编译好了,需要先执行
make clean
然后再执行make
特别需要注意链接 1 代码块 image_data_layer.cpp 中的红字部分,caffe编译时很多错误都是由于caffe版本更新导致的。
三、修改MS_train.prototxt文件
由于在caffe源码中添加了label_dim项,即标签数量,我们需要在训练网络配置文件中的ImageData层添加上 label_dim,含义为属性种类。我这里只有性别和年龄两个属性,所以将label_dim设为2。
image_data_param {
source: "train.txt"
batch_size: 16
#rand_skip: 100
new_height: 256
new_width: 256
shuffle: true
label_dim: 2 #add by brooklyn
}
image_data_param {
source: "val.txt"
batch_size: 8
#rand_skip: 1000
new_height: 256
new_width: 256
shuffle: false
label_dim: 2 #add by brooklyn
}
训练数据和验证数据都要添加上label_dim。
添加slice层:
layer {
name: "slice"
type: "Slice"
bottom: "label"
top: "label_1"
top: "label_2"
slice_param {
axis: 1
slice_point:1
}
}
关于slice layer的具体描述在引用 1 里有,我这里label只有两种属性,所以slice_point 设为了1。
通过slice层将原本网络输出的单个标签分为了多属性标签,在这里是label_1和label_2.后面还需要分别创建这两个层,并且给出各自的损失函数和准确率的计算。
添加多标签全连接层
根据resnet的网络配置文件可以看出,fc5 layer输出256个特征值,这些特征值传递到最后的一个fc中,而这个全连接层fc输出的就是单个属性的类别数,且fc输出到计算损失和准确率的网络层中。
所以我们在添加多属性标签时,将fc5层连接到我们设置的多个属性的全连接层中,而每个属性的全连接层都要连接到损失层和准确率层。
下面给出一个属性的全连接层,这里是性别属性,年龄属性的全连接层类似。
如此,用这两个属性的全连接层替换原来单个标签的全连接层输出即可。
#gender
layer {
bottom: "fc5"
top: "fc_1"
name: "fc_1"
type: "InnerProduct"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
inner_product_param {
num_output: 2
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0
}
}
}
layer {
bottom: "fc_1"
bottom: "label_1"
top: "softmax_loss_1"
name: "softmax_loss_1"
type: "SoftmaxWithLoss"
}
layer {
bottom: "fc_1"
bottom: "label_1"
top: "accuracy_1"
name: "accuracy_1"
type: "Accuracy"
include {
phase: TEST
}
}
以上为第一个属性,添加第二个属性只需复制一遍,且把以上所有出现的全连接层、损失层、准确率层的名字换一个新名字代替,比如末尾由 " _1 " 改为 " _2 " 即可。更多属性依次增加。
四、训练网络
我在训练这个网络时报了一个错误:
Error loading shared library libhdf5_hl.so.
经验老道的工程师给出的解决方法是:
https://github.com/BVLC/caffe/issues/1463
参考上面链接中andyljones的回答,将那两个共享库文件名后缀由7改为8。
此外,在训练过程中如果某个属性的损失过大,可以增大该属性的损失权重,即在损失层中修改loss_weight (默认是1),参考caffe各层的作用 2 。