FCN训练心得
随便用tensorflow搭建了一个FCN8,结构很简单: VGG16从conv1_1到pool5完整拿过来,pool5注意stride改为了2,fc6、fc7变成了1*1的卷积核。然后接3层conv2d_transpose即可,前两个conv2d_transpose分别从pool4和pool3连过来做fuze。tf.AdamOptimizer的学习率用1e-4即可。
抠细节:
1、loss可以这么写:
loss = tf.nn.softmax_cross_entropy_with_logits(logits = self.logits, labels = self.label_tensor)
也可以加:loss = tf.reduce_mean(loss)
这两者都可以收敛。而且曾经有个说法是tf.AdamOptimizer(lr).minimize(loss)内部会把loss求平均。
然后这里要注意tf.nn.softmax_cross_entropy_with_logits接受的logits是没有经过softmax的网络输出值,初学者容易搞不清这里。
2、开始训练之前一定要保证输入数据完全正确!对于semantic segmentation问题,你的label是一张像素图,这个像素很绝对,很可能由于opencv的读入函数,或者resize函数改变了像素点,导致匹配不上label。这里推荐misc库:
from scipy import misc
im = misc.imread("file_name")
im = im.imresize(im, (x,y)) #这里推荐插值方法使用nearest方法,不会改变像素值。
misc库还有一个好处就是对于中文路径的支持比opencv好太多
3、请给网络充足的时间去训练。FCN8训练的时候你可以把它输出的预测结果还原成图片,你会发现在前3000步以前都是黑的。因为背景类站绝大多数嘛,一般在30倍图片数量的迭代次数以后才有图像出现。(这是在图片数量少的情况下,如果图片数量很多,可能只要1-2个epoch就可以看到图像了)
所以在你发现过了几百张图片之后你的结果还是黑屏的时候,不要慌张,尝试把你的softmax结果输出来看看,如果结果是第0类的值远远大于其他类并且该值在大幅变化,那就说明你可以再耐心地等等。
4、刚写完网络的时候最好使用很少的数据进行训练,先看看能不能overfitting,如果可以顺利overfitting了,才可以进行更大数据集上的训练。这样可以有效地降低调试成本。
变种版本:
将conv2d_transpose层换成:tf.image.resize层和一个卷积层。
这个变换也能达到同样收敛的效果,不过是否能够达到同样的精度还有待验证。