本文主要是对fcn在训练过程中的一些总结。我主要是进行了一个二分类和多分类的训练。二分类主要是指路为一类,非路为一类。
先介绍二分类的结果。我是直接使用fcn8s的caffemodel和train.prototxt,加入kitti的数据289张去拟合,横向测试分别用32000代,36000代,40000代,44000代,48000代,52000代和56000代,比较结果是56000代已经学习到马路边的特征,比fcn的效果好但是对于56000代在车上会呈现可行驶区域????
而纵向测试发现,把cityscape的数据放入测试,会发现大块的可行驶区域会检测不到,比原来fcn得到的效果还要差得出结论应该是对kitti的数据过拟合了加入了cityscape的数据集之后,loss一直在100000-400000之间波动不下去
通过修改了output_num,替换了层名,加入cityscape的数据集进行finetune,得到的效果有所改善。
我的finetune主要是修改了反卷积层输出个数以及让反卷积层进行了学习(好像没有意义)再进行finetune,最终的模型对我自己的数据的结果并不是很好。
对于FCN的finetune,注意在Fine-tuning(微调)一个网络的时候, 由于output_num已经改变, 要将所有含有output_num发生改变的层重命名, 原因是在我们下载的caffemodel中已经包含原有的层名称, 而在.prototxt中我们更改了输出参数, 在加载caffemodel时, 如果层名称一样但是数据结构不同, 就会报错, 重命名之后模型中原有的层会被忽略继而使用我们自己定义的新的层。
在FCN的solver.prototxt中有一个iter_size=1,这个参数乘上你的train prototxt中的batch size是你实际使用的batch size。 相当于读取batchsize*itersize个图像才做一下gradient decent(后向传播)。 这个参数可以规避由于gpu不足而导致的batchsize的限制 因为你可以用多个iteration做到很大的batch 即使单次batch有限。
还有FCN的上采样过程实际上就是一个双线性插值过程,就是数字图像处理的二维插值。将特征图放大,然后用crop层剪去多余的部分,使其和ground truth有一样的尺寸以便计算各个像素的预测值。bilinear filtering可以用卷积的形式实现。和前面conv层不同,deconv中卷积核不是随机的,而是根据放大的尺寸生成了与类别相同数量的球形的矩阵。原文中提到deconv中的核可以保持不变或可被训练。作者给的代码中Deconv的学习率为0。
后期加入CRF作为FCN的后处理过程,对于CRF框架的搭建(crfasrnn),最后使用了cuda7.5,cudnnV3和opencv2.4.8搭建成功。
关于CRF,二元势函数就是描述像素点与像素点之间的关系,鼓励相似像素分配相同的标签,而相差较大的像素分配不同标签,而这个“距离”的定义与颜色值和实际相对距离有关。所以这样CRF能够使图片尽量在边界处分割。而全连接条件随机场的不同就在于,二元势函数描述的是每一个像素与其他所有像素的关系,所以叫“全连接”。
注:关于caffe中的概念
epoch——使用整个训练样本集传播一次,一次传播 = 一次前向传播 + 一次后向传播。但是考虑到内存不够用的问题,训练样本们往往并不是全都一起拿到内存中去训练,而是一次拿一个batch去训练,一个batch包含的样本数称为batch size。
iteration——使用batch size个样本传播一次。同样,一次传播=一次前向传播+一次后向传播。
eg. 我们有1000个训练样本,batch size为100,那么完成一次epoch就需要10个iteration。