FCN-for-semantic-image-segmentation 训练过程的一些坑记录

(1)首先,出现layer registry error,提示convolutional layer已经注册过了。网上大多的问题是提示unknown layer,并非already registed,大概有两种针对前一种的解决方法:1.链接的caffe静态库和动态库的区别,应该链接动态库?2.caffe的注册机制的问题,添加头文件,外部强制注册?感觉不太像是我这个问题的答案。查了谷歌,好像是我装了两个版本的caffe导致caffe的路径并未完全设置成其中某个版本的。于是修改.bashrc中所有和caffe有关的路径,修改完后并没有用。但是第二天重新开始训的时候,神奇的可以了。。。。神奇的可以了。。。

(2)第二,训练了几万循环,发现loss一直没有变化。查了查,据说是反卷积层没有初始化weight,查看了代码,代码中有python接口的训练和command line接口的训练,其中我用的一直是command line接口的(就是--solver=。。。。sh train.sh)这个接口没有初始化weight。于是在net.py中deconvolutional layer加入了weight filler 和 bias filler参数(net.py是网络结构的生成文件,修改了以后要执行一下python net.py)。而另一个python接口的代码,已经初始化了合适的weight,用的是VGG16训出来的caffemodel,然而没有成功运行python 接口。于是先自己把command line接口里的weight,初始化了一个高斯随机生成,先跑跑看。

(3)果不其然,loss逐渐减小,但是随着训练次数的增加,其收敛性不是很好,几乎一直处在震荡状态,从3.x左右降到1.x,之后便震荡起来。考虑到没有按照作者的要求初始化合适的weight,也许原因在此,因此还是要继续试试python接口。

 

-----------------

最新更新:

提前说一点,这次训练的是alexnet-FCN。之前用VGG16的caffemodel是不对的,另外下了caffe-net的caffemodel(也就是alexnet)。

之前的训练过程,loss始终振荡,这肯定不对。于是开始处理python接口,把python接口改好后,传入caffenet的caffemodel,使用pre-trained weight,应该可以。这里遇到的问题是python接口执行报错:shape不匹配,即pre-trained的参数数量和训练的alexnet-FCN参数数量不匹配。

这里的解决办法是:http://blog.csdn.net/zouyu1746430162/article/details/53787706。使用神奇的surgery.transplant函数,把两个网络的参数统一起来。

另外注意的一点就是一定要把训练数据,validation数据,test数据的路径搞清楚,改对。

于是就可以了,训练,到了8000轮的时候,一个统计结果是mIU达到41.8%,和程序说明里的48%还有一点差距,不过loss已经明显收敛,达到0.45左右。

至此,这个demo算是真正跑通了。不容易!

总结:

两次weight没有准确初始化:第一次,loss不变,是因为反卷积层(原alexnet并没有这一层)参数没有初始化,并且错误的拿VGG16的参数给alexnet初始化(在command line接口的solver里面)。第二次,loss振荡,也是错误的拿VGG16的参数给alexnet初始化的锅。

shape 不匹配:即然是把原始alexnet改成了alexnetFCN,如果不用transplant,会在fc6层之后,出现参数数量的不一致,因为后者网络的输入尺寸和经典alexnet的输入尺寸不一定一样,所以报错也是出现在fc6层的shape。

 

-------------

后续疑问:

(1)FCN在网络结构和参数定了之后,能接受任意尺寸的输入图片吗?如果可以,最后的输出尺寸肯定不一致,那么如何统一结果?

(2)FCN的全连接转卷积层是怎么转的?这个可以看http://blog.csdn.net/zizi7/article/details/49506979。基本明白了。

(3)FCN是怎么拿pre-trained的参数作为初始weights的?如何保证参数数量匹配?多出的deconvolutional layer怎么办?这个要看surgery.transplant函数找启发。

(4)如何能给FCN的结果加上CRF来refine边缘?能试着写写吗?

-------------

对于疑问(1)的一些想法:之所以说FCN的网络结构和参数确定了以后,可以接受任意尺寸的输入,是基于和传统最后是全连接层的alexnet等比较;对于传统网络(最后是全连接层),一旦输入尺寸有变化,则到达全连接层的前一个卷积层的输出尺寸,必然会随着改变,这个尺寸一改变,全连接的边的数量就改变,总的训练权值数量就改变,这样,既定的权值数量就变化了。然而一旦网络确定,这个权值数量在整个训练过程是不能变的,因此才说传统网络有这个缺陷。

对于FCN,所有的权值参数,都是基于卷积核的参数,下一层是由卷积核作用于上一层产生,而非单纯通过全连接相连。因此,只要每层的卷积核大小定了,在保证stride满足条件的情况下,的确可以使网络接收任何可能大小的输入,也就是说整个训练过程,总的权值数量是不变的。其结果的唯一区别也是最后的feature map大小不同。然而feature map是需要再进行deconv的,deconv又是基于卷积核的参数,最终通过crop,生成和原始图像大小一致的结果,因此也不存在统一结果的问题,因为结果最终都是和原始输入大小一致。

 

----------------

对于疑问(3),通过分析surgery_transplant函数,外加http://www.cnblogs.com/zjutzz/p/6185452.html这篇对于caffemodel文件的结构分析,可知,权重赋值只作用于新旧网络中重合的层和相应参数,对于非重合的层及参数,简单的drop。这也是为什么deconv层需要单独初始化权值的原因,因为传统alexnet是完全没有deconv层的,新网络里面这个层的参数就无从而来。但这也启发了我fc6、fc7、以及score_fr这三层也是新层,其参数也没有初始化,看来这一点之前训练的时候是做的不对的。

posted @ 2017-01-27 09:19  吕吕吕吕吕  阅读(5806)  评论(1编辑  收藏  举报