finetune训练模型

在已有模型上finetune自己的数据训练一个模型

准备训练数据和测试数据

制作标签

数据转换,将图片转为LMDB格式

前三步的过程和 如何利用自己的数据训练一个分类网络 是一样的,参考处理即可。

修改网络模型文件

复制/caffe-root/models/finetune_flickr_style文件夹下面的deploy.prototxt readme.md solver.prototxt train_val.prototxt四个文件到自己的finetune项目根目录/caffe-root/models/finetune_test/下

vim train_val.prototxt

  • 修改train_val.prototxt中的数据层,设置成caffeNet中的train_val.prototxt一样,使用lmdb输入数据。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
layer {
name: "data"
type: "Data"
top: "data"
top: "label"
include {
phase: TRAIN
}
transform_param {
crop_size: 227 # 传入的图片是256*256,现在在其中框出一个227*227的小图片 以此来增大训练集
mean_value: 104 # 通用均值
mean_value: 117
mean_value: 123
mirror: true # 镜像操作 扩大数据集
}
data_param {
source: "/home/weijian/caffe/models/classification_CNN/lmdb/train"
batch_size: 100
backend: LMDB
}
}
layer {
name: "data"
type: "Data"
top: "data"
top: "label"
include {
phase: TEST
}
transform_param {
crop_size: 227
mean_value: 104
mean_value: 117
mean_value: 123
mirror: false
}
data_param {
source: "/home/weijian/caffe/models/classification_CNN/lmdb/test"
batch_size: 50
backend: LMDB
}
}
  • 修改最后的一个全连接层fc8_flickr,finetune的目的是重塑最后这个全连接层fc8_flickr,其他层的参数不变。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
layer {
name: "fc8_flickr" # 原网络结构文件中,最后的一层就是fc8,我们在这里希望自行设计最后一层,所以我们齐了另外一个名字fc8_flickr,如果还是继续沿用fc8这个名字,就会造成finetune的时候,以前caffemodel里面的参数和权值直接填充进去。
type: "InnerProduct"
bottom: "fc7"
top: "fc8_flickr"
# lr_mult is set to higher than for other layers, because this layer is starting from random while the others are already trained
param {
lr_mult: 10 # 基本学习率乘以10
decay_mult: 1
}
param {
lr_mult: 20
decay_mult: 0
}
inner_product_param {
num_output: 5 # 这里根据实际情况,有几种数据,就改成几。因为有house、flower、animal、guitar、plane五种数据,所以改成了5。
weight_filler {
type: "gaussian"
std: 0.01
}
bias_filler {
type: "constant"
value: 0
}
}
}

注意,这个fc8_flickr层下面的Accuracy层的bottom是fc8_flickr。

vim deploy.prototxt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
layer {
name: "fc8_flickr"
type: "InnerProduct"
bottom: "fc7"
top: "fc8_flickr"
# lr_mult is set to higher than for other layers, because this layer is starting from random while the others are already trained
param {
lr_mult: 10
decay_mult: 1
}
param {
lr_mult: 20
decay_mult: 0
}
inner_product_param {
num_output: 5 # 这里只是修改num_output为5即可。
weight_filler {
type: "gaussian"
std: 0.01
}
bias_filler {
type: "constant"
value: 0
}
}
}

修改超参数文件

修改net为刚刚我们修改的那个train_val.prototxt

还需要修改test_iter、test_interval、snapshot_prefix、solver_mode、type等内容

因为是在做微调,所以设置base_lr很小,仅为0.001。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
net: "/home/weijian/caffe/models/finetune_test/train_val.prototxt"
test_iter: 30
test_interval: 250
# lr for fine-tuning should be lower than when starting from scratch
base_lr: 0.001
lr_policy: "step"
gamma: 0.1
# stepsize should also be lower, as we're closer to being done
stepsize: 10001000的迭代降低学习率:乘以gamma
display: 100
max_iter: 150000
momentum: 0.9
weight_decay: 0.0005
snapshot: 5000
snapshot_prefix: "/home/weijian/caffe/models/finetune_flickr_style/models/type"
# uncomment the following to default to CPU mode solving
type: "AdaDelta"
solver_mode: GPU

训练模型

vim train.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/usr/bin/env sh
set -e

log_path="logs/"
mkdir -p $log_path

save_model_path="caffemodel/"
mkdir -p $save_model_path

# training log
file_prefix="classification_CNN"
log_file=$(date -d "today" +"%Y-%m-%d-%H:%M:%S")
log_file=$log_path$file_prefix$log_file".log"

# caffe execute file path
caffe_bin="/home/weijian/caffe/build/tools/caffe"


# finetune
$caffe_bin train --solver=solver.prototxt --weights=bvlc_reference_caffenet.caffemodel 2>&1 | tee ./logs/finetune_test.log

测试

修改以下部分,其余和 这里 一样。

1
2
3
4
#网络结构描述文件
deploy_file = caffe_root+'models/finetune_test/deploy.prototxt'
#训练好的模型
model_file = caffe_root+'models/finetune_test/models/solver_iter_15000.caffemodel'

finetune的好处

如果我们想自己训练一个效果较好的模型,需要大量的数据,非常优秀的硬件条件,以及漫长的训练时间,但是,我们可以利用现有的caffemodel模型训练利用较少的数据训练一个效果较好的模型。