进行finetune的命令如下:
..\..\bin\caffe.exe train --solver=.\solver.prototxt -weights .\test.caffemodel
pause
下面介绍caffe.exe的几个参数:
1)这里caffe.exe中第一个参数为train表示训练,如果为test表示进行测试
2)不论是finetune还是从头开始的训练,都必须指明solver文件,这个用--solver 指明。下面会介绍finetune时,solver文件的修改以及对应的trian_val和 deploy的修改 。
3)finetune必须指明进行微调的caffemodel,这个用-weights指明。
这里再补充几点实际操作时需要注意的地方:
1. ImageNet原来是1k个类别,finetune时需要根据自己数据集的类别数重新设置fc8层的output数,且新的fc8层的blob_lr会设的大一些(比如10和20),是为了加快收敛。
2. 如果你的网络中某一层的的参数个数变了,例如AlexNet全连接层输出为1000个,而你的网络只需要做2分类也就是输出两个值,那一定要把该层的 name 换一下,不然caffe 在 finetune 源网络的weight 的时候发现维度不匹配会报错的。
3. 自己数据集的类别号从0开始,中间要连续(我师弟有次finetune数据集一直报错,后来发现他是二类分类,但是类别号设成了0和12)
4. 数据集记得打乱,不然很可能不收敛
5. 如果出现不收敛的问题,可以把solver里的lr设的小一点,一般从0.01开始,如果出现loss=nan了就不断往小调整
6. 可以把accuracy和loss的曲线画出来,方便设定stepsize,一般在accuracy和loss都趋于平缓的时候就可以减小lr了
solver.prototxt:
(1)如果之前文件名没改的话则不需要更改以上两项,否则改为对应文件。其他参数根据实际需要更改。
# The training protocol buffer definition
train_net: "G:/caffe-windows-master/examples/car/train_val.prototxt"
# The testing protocol buffer definition
test_net:"G:/caffe-windows-master/examples/car/train_val.prototxt"
或者当训练和测试使用一个prototxt时,可以使用net一次就好。
net: "train_val.prototxt"
(2)学习速率,由于finetune是在局部进行微调,因此学习速率不能太大,我们希望学习速率能随着迭代的次数不断降低,而且学习速率降低的幅度更快一些。这样以来,在使用step的策略时,stepsize可以更小一些。
# lr for fine-tuning should be lower than whenstarting from scratch
#直接从原始数据训练的base_lr一般为0.01,微调要比0.01小
base_lr: 0.001
lr_policy: "step"
gamma: 0.1
# stepsize should also be lower, as we're closer tobeing done
#要比直接训练的小一些,直接训练的stepsize为100000
stepsize: 50000
momentum: 0.9
在迭代的过程中,可以对基础学习率进行调整。怎么样进行调整,就是调整的策略,由lr_policy来设置。
lr_policy可以设置为下面这些值,相应的学习率的计算为:
·
· -fixed: 保持base_lr不变.
· - step: 如果设置为step,则还需要设置一个stepsize, 返回
base_lr * gamma ^ (floor(iter / stepsize)),其中iter表示当前的迭代次数
· - exp: 返回base_lr * gamma ^ iter, iter为当前迭代次数
· - inv: 如果设置为inv,还需要设置一个power, 返回base_lr * (1 + gamma* iter) ^ (- power)
· -multistep: 如果设置为multistep,则还需要设置一个stepvalue。这个参数和step很相似,step是均匀等间隔变化,而multistep则是根据 stepvalue值变化
· -poly: 学习率进行多项式误差, 返回 base_lr (1 - iter/max_iter) ^ (power)
· -sigmoid: 学习率进行sigmod衰减,返回 base_lr ( 1/(1 +exp(-gamma * (iter - stepsize))))
(微调)Stepsize为50000,即前50000次迭代使用0.01的学习率,50000到100000次迭代使用0.01*0.1=0.001的学习率,100000到1500000次迭代使用0.01*0.1*0.1=0.0001的学习率。。。。。
(直接训练)Stepsize为100000,即前100000次迭代使用0.01的学习率,100000到200000次迭代使用0.01*0.1=0.001的学习率,200000到3000000次迭代使用0.01*0.1*0.1=0.0001的学习率。。。。。
display: 100
max_iter: 100000
weight_decay: 0.0005 #权值衰减系数
snapshot: 2000
snapshot_prefix: "tr"
# uncomment the following to default to CPU modesolving
# solver_mode: CPU
deploy.prototxt:
(1)文件开头:
input: "data"
input_shape {
input_dim: 10
input_dim: 3
input_dim: 227
input_dim: 227
}
分别为一次导入的图片个数,channel,heigth ,width。
(2)倒数第二层,即输入给softmax层数据的那层,其中的num_output需要更改为实际图片的label数,即图片类别数。否则在进行训练时,会出现错误。
layer {
name:"fc8"
type:"InnerProduct"
bottom:"fc7"
top:"fc8"
param {
lr_mult: 1
decay_mult:1
}
param {
lr_mult: 2
decay_mult:0
}
inner_product_param {
num_output: 1000
weight_filler {
type:"gaussian"
std: 0.01
}
bias_filler{
type:"constant"
value: 0
}
}
}
train_val.prototxt
这里使用IMGEDATA数据,如果训练多通道图片,最好有一个meanfile参数。
layer {
name:"data"
type: "ImageData" #数据来源于图片
top:"data"
top:"label"
include {
phase:TRAIN #数据用来训练
}
transform_param {
mirror:false # 1表示开启镜像,0表示关闭,也可用ture和false来表示
# 剪裁一个 227*227的图块,在训练阶段随机剪裁,在测试阶段从中间裁剪
#因为在deploy中指明训练图片是227*227,这里剪裁为 227*227的图块
crop_size: 227
#在微调时,这个meanfile必须为生成caffemodel样本的meanfile
mean_file:"data/ilsvrc12/imagenet_mean.binaryproto"
}
image_data_param{
source: "/car/trian.txt" #图片的说明文件
batch_size: 50 #每一次处理的数据个数,即图片数
new_height:256 #将图片进行resize
new_width:256 #将图片进行resize
}
}
【注】这里需要说明两点:
(1) new_height和new_width 可以不设置,这样以来就是原始图片的大小。比如我裁剪的车辆图片是24*24,如果不设置new_height 和new_width ,这样会导致caffe运行出错,因为无法在一幅24*24的图片中裁剪出一个227*227的图片。因此,当原始图片小于227*227时,必须进行resize。
(2) 图片说明文件的生成:
a) 分别在训练的正样本和负样本文件夹下使用dir /s/b > train.txt生成训练的正样本和负样本目录。然后将正样本目录中的bmp(或者jpg)替换为bmp 1(或者jpg 1);将负样本目录中的bmp(或者jpg)替换为bmp 0(或者jpg 0)。
b) 将正负样本的说明文档拷贝到一个txt中。
c) 需要将正负样本的顺序打乱,这样训练的效果比较好。这里使用了一个打乱文本行的小工具,将b)中的文本放入这个小工具中,就会在工具的根目录下生成一个打乱了行顺序的文本文件。
官方的资料里面已经讲的非常详细了,
http://caffe.berkeleyvision.org/gathered/examples/finetune_flickr_style.html
这里再补充几点实际操作时需要注意的地方:
1. ImageNet原来是1k个类别,finetune时需要根据自己数据集的类别数重新设置fc8层的output数,且新的fc8层的blob_lr会设的大一些(比如10和20),是为了加快收敛。
2. 如果你的网络中某一层的的参数个数变了,例如 AlexNet全连接层输出为1000个,而你的网络只需要做2分类也就是输出两个值, 那一定要把该层的 name 换一下,不然 caffe 在 finetune 源网络的 weight 的时候发现维度不匹配会报错的。
3. 自己数据集的类别号从0开始,中间要连续(我师弟有次finetune数据集一直报错,后来发现他是二类分类,但是类别号设成了0和12)
4. 数据集记得打乱,不然很可能不收敛
5. 如果出现不收敛的问题,可以把solver里的lr设的小一点,一般从0.01开始,如果出现loss=nan了就不断往小调整
6. 可以把accuracy和loss的曲线画出来,方便设定stepsize,一般在accuracy和loss都趋于平缓的时候就可以减小lr了