图像语义分割(Image sematic segmentation)学习了将近一年,日常学习中遇到的问题,都喜欢记录到有道云笔记里,一年下来,列表里全是yyyy-mm-dd的笔记名。趁着这段时间空闲整理下,也方便共享和志同道合的小伙伴交流。由于基础不好,加上本人是一枚“较真”的小硕,因此,多数笔记均是关于细节性,当然更多的可以给入门的同胞一些借鉴,大牛们可以绕道~


1.论文

前提:当然需要深度学习的一些基础知识啦~可以从UFLDL开始。 对于准备入门的小伙伴,建议从具体的一篇paper开始,有两条思路:

1、从最基础的开始,比如FCN《Fully Convolutional Networks for Semantic Segmentation》,后期的很多论文都是在这个基础上进行改进的,在整体了解pixel-level,end to end的是怎样实现的后,再看后期改进的论文比如:DeepLab-CRF 、CRFasRNN 等,可以参考多篇用DL做Semantic Segmentation的文章总结 【双手合十感谢博主!(•̀∀•́)棒】

2、从最新的论文开始,然后根据论文中的参考文献追溯以前的论文,哪一点不理解就去看哪一篇论文,引用我导师经常说的一句话“顺藤摸瓜,早晚能搞透彻”。

以下是在看论文的时候几点建议: 1、明白论文的创新点所在,这点对所有的科研论文都适用; 2、分析清楚网络结构,可以借助Quick Start实现,可以通过手动画图,来看自己是否理解的透彻; 3、各种类型层的具体运算是如何实现的,参数配置,写法; 4、看FCN的时候,弄明白论文最后的几个分割评估指标mean IU等。否则在以后的实验中,看着终端刷刷的数据,却不知道哪个是你想要的。明白目标很重要。
5、做好笔记、做好笔记、做好笔记!重要的事情说三遍,在总结的的过程中,结合自己的课题会激发自己的思维,总结多了,会发现牛人是怎么去找创新点的,就会有点灵感了。
另外自己一点点感悟,适当的结合下传统图像处理方法,不知道指引的方向是否妥当,总感觉传统的图像处理方法才是本。(灬°ω°灬)

2、实验

 千万不要以为有了思路后再去做实验,纸上谈兵永远不靠谱,做实验的过程也会激发自己的思维,但是也不要拿到一个论文就迫不及待的去实现,毕竟需要时间,在结合自己的课题觉得有所帮助后,再去实验,从实验总发现问题,然后改进。(o゜▽゜)o
[BINGO!]做笔记,做笔记,做笔记!总结真的很重要!

 对于基础比较弱的同志,往往会在试验的时候懊悔自己编程代码能力太渣,于是乎~掉头专门去学习基础语法比如Python,matlab,真的不要这样,用的时候不会就去查,及时的解决问题才是关键的。专门去学习需要有计划,有系统的时间安排,千万不要头脑一热就去学习。另外大家会在选择python和matlab之间动摇,建议Python。

 遇见问题的第一时间是想办法百度谷歌自己找办法解决,而不是截图贴出来问别人,毕竟授人鱼不如授之以渔,所以简单的自己解决,有深度的可以拿出来探讨一下。

哈哈~~~~~~是不是有点偏题了。本是想把自己的学习笔记总结一下的。但是这些东西也是蛮重要的哟!

—————————————————————–不知所云分割线—————————————————————————-

本喵去吃饭了,回来继续敲…(ΦωΦ)

好了,今天520,学校食堂的饭竟然买一送一,吃饱饱回来继续咯(✪ω✪)

—————————————————————–不知所云分割线—————————————————————————-
以下为FCN实验中遇到的琐碎的小问题(欢迎大家拍砖指正):

1、很多小朋友想用自己的数据做实验,very good,但是数据的标注很麻烦的。按照VOC数据集的格式,手工进行标注的吧,可以用类似的PS抠图,将不同目标区域标注为不同的颜色,然后按照不同的颜色索引表转换成索引格式的图像,即为标签(Ground Truth)。(づ。◕ᴗᴗ◕。)づ看这里→ VOC Segmentation GT图像颜色表生成分析,看见群里很多人问有没有什么方便的工具自动标注的,那么如果都能自动标注了,那还要我们后续的工作有什么意义呢?
先附上几篇参考的重链接:
使用FCN做语义分割(实践篇):
理论分析:,
对应github上源码:https://github.com/wkentaro/fcn/blob/master/fcn/pascal.py
VOC segmentation GT图像颜色表生成分析:

2、FCN作者给出的开源代码中网络结构中数据层是Python类型的,文件voc_layer.py中作者写的类VOCSegDataLayer、SBDDSegDataLayer实现了接受图片和标签的输入。
从网络结构看起

train.prototxt
layer {
  name: "data"
  type: "Python"
  top: "data"
  top: "label"
  python_param {
    module: "voc_layers" 
    layer: "VOCSegDataLayer"
    param_str: "{\'voc_dir\': \'/home/caffe-master/fcn_example/voc\', \'seed\': 1337, \'split\': \'train\', \'mean\': (181.731, 178.280, 177.170)}"
  }
}

module:为你自己的数据接受文件名称,作者为voc_layers.py
layer:voc_layers.py中选择接收数据定义的类,有VOCSegDataLayer、SBDDSegDataLayer两种
param_str中是键值对的方式出现的,其中voc_dir对应的是数据集的路径,split指明是训练数据还是验证(train,val),mean是数据集在RGB三个通道的均值。

再看voc_layers.py

由于我只用了VOCSegDataLayer,因此把另外一个class直接删掉了。

class VOCSegDataLayer(caffe.Layer):
          ...
        # load indices for images and labels
        # 这里的{self.voc_dir}/ImageSets/{self.split}.txt是读取image和label时用到的路径,其中voc_dir是train.prototxt中数据集路径,split是指定训练或者验证数据集,train.txt或者val.txt.
        split_f  = '{}/ImageSets/{}.txt'.format(self.voc_dir,
                self.split)
        self.indices = open(split_f, 'r').read().splitlines()
        self.idx = 0

   ...

# 读入的时候是图像,转换成神经网络可以接受的blob,
    def reshape(self, bottom, top):
        # load image + label image pair
        self.data = self.load_image(self.indices[self.idx])
        self.label = self.load_label(self.indices[self.idx])

        # reshape tops to fit (leading 1 is for batch dimension)
        # 这里的top[0]/top[0]分别为图像和标签,reshape(1,..)中的1位batchsize,这里的batchsize自己可以修改,只要显存允许,当然是越大越好啦~
        top[0].reshape(1, *self.data.shape)
        top[1].reshape(1, *self.label.shape)
   ...
       #读入image
    def load_image(self, idx):
       ...

    def load_label(self, idx):
       ....

代码中load_image中对图像进行格式转换的具体每一步的意义可以参考薛的笔记
遇到no module named voc_layer。这个问题之前遇到过,将voc_layers.py文件拷贝到voc-fcn8s文件夹下即可解决。

3、[Caffe]: Check failed: ShapeEquals(proto) shape mismatch (reshape not set)
原因:是因为用自己的数据进行fine-tune的时候,没有更改网络各层参数的名字,导致加载caffemodel的时候加载了pre-train的参数,从而导致参数和数据不匹配。 解决办法:http://www.it610.com/article/5029969.htm

4、训练方式:python solve.py >& fcn.log &
其中‘>&’表示所有的标准输出(stdout)和标准错误输出(stderr)都将被重定向,fcn.log为重定向后log保存的文件,最后的&表示将命令放入后台执行。
为了观察是否正常运行,可以在运行阶段,使用’tail -f fcn.log‘连续观测log文件的更新,退出请使用Ctrl+C

不要用caffe train –solver=xxx这种方式来跑代码,说是会导致后边的deconvolution层没有办法初始化,会造成参数都为0,从而导致loss一直保持很大的数值不变动 ,所以如果loss的数值不变的情况下,。请改用sovle.py文件来调用caffe训练,里边会有一些初始化这些参数的过程。

5、关于训练的时候solve.py中weight的加载可以参考一生不可自决博客:

宝宝没有午休,有些累了,回更………………..(бвб))zzz

—————————————————————–课间操分割线—————————————————————————-

6、通过训练曲线,可以评估当前训练状态:

  • train loss不断下降,test loss不断下降,说明网络仍在认真的学习
  • train loss 不断下降,test loss 区域不变,说明网络过拟合
  • train loss趋于不变,test loss趋于不变,说明学习遇到瓶颈,需减小学习速率或批量数据尺寸
  • train loss趋于不变,test loss不断下降,说明数据集100%有问题
  • train loss不断上升,test loss不断上升(最终变为NAN),可能是网络结构设计不当,训练超参数设置不当,程序bug等某个问题引起的,需要进一步定位。

附上Matlab代码用来画训练曲线:

clear;
clc;
close all;
% 这个参数用来指定 Caffe 运行 log 文件
% 生成 log 文件方法:./examples/cifar10/train_quick.sh  >& cifar.log&
train_log_file = 'cifar.log';
% 这个参数相当于 solver.prototxt 中的 display 值
train_interval = 100;
% 这个参数相当于 solver.prototxt 中的test_interval 值
test_interval = 500;


[~, string_output] = dos(['cat ', train_log_file, ' | grep ''Train net output #0'' | awk ''{print $11}''']);
% fid = fopen('matlab_train_loss', 'r');
% train_loss = fscanf(fid, '%f\n');
% fclose(fid);
train_loss = str2num(string_output);
n = 1:length(train_loss);
idx_train = (n - 1) * train_interval;

% fid = fopen('matlab_test_loss', 'r');
% test_loss = fscanf(fid, '%f\n');
% fclose(fid);
[~, string_output] = dos(['cat ', train_log_file, ' | grep ''Test net output #1'' | awk ''{print $11}''']);
test_loss = str2num(string_output);
m = 1:length(test_loss);
idx_test = (m - 1) * test_interval;
figure;plot(idx_train, train_loss);
hold on;
plot(idx_test, test_loss);

grid on;
legend('Train Loss', 'Test Loss');
xlabel('iterations');
ylabel('loss');
title(' Train & Test Loss Curve');