如何进行finetune

进行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了

猜你喜欢

转载自blog.csdn.net/nongfu_spring/article/details/51514040