caffe下fine-tune的demo

fine-tuning:利用已有模型训练其他数据集

Deep Learning或者说CNN在图像识别这一领域取得了巨大的进步,那么自然我们就想将CNN应用到我们自己的数据集上,但这时通常就会面临一个问题:通常我们的dataset都不会特别大,一般不会超过1万张,甚至更少,每一类图片只有几十或者十几张。这时候,直接应用这些数据训练一个网络的想法就不可行了,因为深度学习成功的一个关键性因素就是大量带标签数据组成的训练集。如果只利用手头上这点数据,即使我们利用非常好的网络结构,也达不到很高的performance。这时候,fine-tuning的思想就可以很好解决我们的问题:我们通过对ImageNet上训练出来的模型(如CaffeNet,VGGNet,ResNet)进行微调,然后应用到我们自己的数据集上。

由于ImageNet数以百万计带标签的训练集数据,使得如CaffeNet之类的预训练的模型具有非常强大的泛化能力,这些预训练的模型的中间层包含非常多一般性的视觉元素,我们只需要对他的后几层进行微调,在应用到我们的数据上,通常就可以得到非常好的结果。最重要的是,在目标任务上达到很高performance所需要的数据的量相对很少

这是Caffe官方提供的fine-tuing示例:Caffe | Fine-tuning for style recognition

下面我们看另外一个有趣的例子:

Oxford flowers分类

我修改了他们的一些代码,使用了VGG_16而不是VGG_S模型,得到了更好的结果。

这是一个给花分类的例子,我们首先

git clone https://github.com/fish145/fine-tuning
cd Oxford102
  • 1
  • 2

克隆整个项目到本地,然后使用

python bootstrap.py
  • 1

准备图片,并下载CaffeNetVGG-16这两个预训练模型

这里写图片描述

运行结束之后我们就可以看到这些美丽的图片了

这里写图片描述

可以看到,总共8189张图片被划分为训练集(1020张),验证集(1020张)和测试集(6149张)

1.微调CaffeNet

CaffeNet

1).CaffeNet包含五层卷积层和三层全连接层,我们保留前面七层的参数,修改最后一层fc8为fc8_oxford_102,将最后预测种类设置为102,相当于我们只需要着重训练这一层的参数,而微调前面的七层

看一下配置文件中值得注意的地方:

这里写图片描述

这是输入部分,我们这里使用ImageData的形式作为Input,train.txt和valid.txt就是上面程序生成的数据列表,没有使用以往常用的lmdb格式。因为作为微调,数据量相对很少,所以使用这种比较慢的形式也是可以接受的

2).然后设置base_lr为0.001(原始模型中为0.01),因为我们只需要微调前面几层的结构,而将最后一层的learning_rate设置为0.01,来加快这一层的学习;如果你想完全停止除fc8_flickr外其他层的微调,你可以设置那些层的lr_mult为0

看一下solver.prototxt:

这里写图片描述

可以看到除了base_lr和stepsize被修改外,其余参数都基本一致

这里写图片描述 
这里写图片描述

新加入的fc8_oxford_102层的learning_rate是前七层的十倍

3).stepsize也需要设置的小一点

接下来开始训练,采用标准的训练过程,用验证集来调整参数,用测试集来测试最终的模型

caffe train -solver=solver.prototxt -weights=pretrained-weights.caffemodel -gpu 0
  • 1

用以上命令进行训练:

这里写图片描述

单GPU上训练50000次用了六个小时左右,但其实三万次的模型在测试集上的performance最高,后面应该出现了点过拟合,我们看一下训练过程中的accuracy曲线图

这里写图片描述

这里写图片描述

oss下降的非常快,大致30000次迭代之后,已经达到最佳

接下来我们在测试集(6149张)图片上测试我们的模型:

caffe test -model=test.prototxt -weights=snapshot.caffemodel -iterations=123 -gpu 0
  • 1

这里写图片描述

最后的accuracy为81.43%,在验证集上的accuracy为84%左右,可以看出模型泛化能力还是非常好的

最后我们用训练出来的模型对自己的图片进行预测:

python predict.py test1.jpg deploy.prototxt pretrained.caffemodel ilsvrc_2012_mean.npy 227
  • 1

参数依次是测试的图片,配置文件,model,均值文件以及crop之后的图片size

这里写图片描述 
这里写图片描述

itle为花的种类以及为该种类的概率。

如果有数量庞大的花的数据以及一些额外工作,我们就可以得到一个识花的工具了!


尝试将前五层的卷积层的lr调成0,只训练全连接层,在验证集上的结果如下图:

这里写图片描述

82.85%,和之前的结果(83.95%)相比只下降了1%,再看一下测试集上:

这里写图片描述

也只下降了1%左右,但是训练时间并没有差多少,也是6个小时左右,所以用CaffeNet进行fine-tuning的话,这种策略并没有什么收益!

2.微调VGGNet(16 layers)

VGG_16

VGG_16包含13个卷积层和3个全连接层,和上面一样,我们只修改最后一层,具体的结构大家参考项目下的配置文件即可

由于这个结构比较庞大,单GPU(Tesla K80)训练大概需要两天时间~

这里写图片描述

30000次迭代后,accuracy达到了89.1%,比CaffeNet结构提高了接近6%!如果使用现在最好的ResNet结构,应该可以达到90%以上的accuracy

下面比较一下二者的训练曲线:

这里写图片描述

然后看一下在测试集上的表现:

这里写图片描述

在测试集上的accuracy86.3%,同样是一个飞跃!这一结果已经无限逼近这个数据集上目前的最佳结果了(87%,使用SVM方法)

最后测试自己的图片就不进行了,感兴趣的可以自行尝试,这个model比前一个的识别能力要更好


尝试将前十三层的卷积层的lr调成0,只训练后三层全连接层,结果如下:

这里写图片描述

accuracy降到81.56%了,在测试集上更是连80%也没有:

这里写图片描述

但是训练时间降低到了16个小时,整整快了两倍左右,但是对performance影响太大,所以也不推荐使用;

在层数较深的情况下,由于DL本身的特性,在越高层形成的特征越抽象,而前面的卷积层则是颜色和边缘这些比较泛化的特征,所以在fine-tuning时,可以将前几层conv层的lr置为0,但是后面的conv不建议这么做,否则对performance影响太大,得不偿失!


3.微调ResNet(50 layers)

最近使用fine-tuning完成了一个task,为达到最好的performance,使用了50层的ResNet结构。中间也遇到一些坑,一起写在这里,给大家一个借鉴。 
1)数据转换

由于50层的结构太深了,所以我们需要将数据转换成lmdb格式,否则训练起来太慢了,这里使用caffe提供的convert_imageset.ex。

convert_imageset.exe --shuffle --resize_height=256 --resize_width=256 <root>/ train.txt oxford102_train_lmdb
  • 1

–shuffle代表打乱数据顺序,–resize代表将图片resize至指定尺寸,/为图片所在的根目录,然后是文件集和生成的lmdb数据库名,我们将train,test和valid均转换成lmdb文件

2)生成配置文件

Kaiming大神给我们提供了他们训练出来的模型:OneDrive

也有deploy.prototxt,可以参考deploy用一个script来生成。关于model,值得一提的是,官方的model只有conv1有bias_term,后面的那些卷积层均没有偏置项,所以在生成prototxt时,需要把那些层的bias_term禁用。(这个地方,当时被坑了很久,后来找了很长时间,终于找到了这个bug)

3)训练

使用了两块K80的GPU来进行训练,一是为了缩短训练时间,二则一块GPU没有那么大的显存。最终只花了16个小时就迭代了5万次,也可以看出LMDB数据库的高效性!

这里写图片描述

再验证集上达到了91.37%的Accuracy.

这里写图片描述 
这里写图片描述

再来看一下测试集上的表现:

这里写图片描述

达到了88.08%的准确率,超过了目前在这一数据集上表现最好的SVM方法(87%)

ResNet果然没有让人失望!

转自https://blog.csdn.net/luojun2007/article/details/76376694

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页