MATCONVNET进行FCN语义分割

CN语义分割算法已经在很多主流深度学习平台上实现了,包括Caffe、TenserFlow、MatConvNet等。这篇博客主要介绍如何在MatConvNet上运行起FCN语义分割,包括CPU和GPU版本。博主的平台是Matlab2017a+Cuda8.0。

  • 下载中心
  • 配置步骤
    • 1.下载代码
    • 2. 配置MatConvNet
      • 2.1 使用CPU
      • 2.2 使用GPU,CUDA加速
      • 2.3 编译MatConvNet
    • 3.下载数据
      • 3.0 VGG-VD-16预训练模型
      • 3.1 训练数据
      • 3.2 预训练模型
    • 4.调试训练
      • 4.1 运行调试
      • 4.2 预训练调试
  • 测试
  • 致敬

下载中心

  • FCN-Paper论文:下载地址 [可选]
  • MatConvNet:下载地址 
  • FCN-MatConvNet:下载地址
  • VOC2011训练数据:下载地址[voc10],下载地址[voc11],下载地址[voc12]
  • VOC12语义分割Benchmark:下载地址
  • MatConvNet-VGG预训练模型:下载地址
  • MatConvNet-FCN预训练模型:下载地址 [可选]
  • Caffe FCN预训练模型:下载地址 [可选]
  • CUDA加速,cuDNN运行库:下载地址 [可选]

配置步骤

1.下载代码

这里需要下载两份代码,一个是FCN的代码,另一个是MatConvNet代码,将MatConvNet中的代码放入根目录下,将文件夹名重命名为matconvnet。

2. 配置MatConvNet

2.1 使用CPU

使用CPU的话直接编译就可以了,不需要进行额外配置。(至少博主目前使用的v1.0-beta23是这样,如果你使用的版本不同最好参照官网说明)。具体编译过程参见2.3的代码

2.2 使用GPU,CUDA加速

需要有支持cuda的显卡,在英伟达官网下载cudnn库,将文件放入local文件夹下。

同时,在编译MatConvNet过程中,需要指定该文件夹,参见下面的编译代码。

2.3 编译MatConvNet

下面的脚本是博主写的,原先代码里面没用,使用enableGpu变量来控制是否编译GPU版本,每次切换平台都需要重新编译,所以有个if 1控制是否重新编译。使用GPU时注意下面的路径设置,配置好之后直接运行下面的脚本就可以了。

如果是cuda7.5及以下,直接使用官方版本的MatConvNet就可以了,博主使用cuda8.0,在使用的时候做了些修改,具体改了哪些博主也忘记了(当时跑一个跟踪demo,改的时候也没注意,反正就是名字啊,目录啊什么的,自己debug完全可以解决),后面会释出博主修改后的matconvnet。

如果出现编译错误,那么就需要自己定位错误,自己debug了,可能出现问题的原因主要有:编译环境配置(编译器,路径,cuda版本等),代码版本问题(目前博主没遇到过,因为MatConvNet在历史上有几次大变动,模型数据格式都变了,所以版本对应是可能导致问题的原因之一)等等0.0

3.下载数据

3.0 VGG-VD-16预训练模型

这里要知道,FCN是会调用VGG模型的,所以要下载 imagenet-vgg-verydeep-16.mat 模型文件,并方法./data/models/文件夹下。

3.1 训练数据

在下载中心下载数据,放入./data/archives文件夹下,并根据代码中的设置重命名:

根据选择版本的voc数据库 重命名为 VOC2010trainval.tar/ VOC2011trainval.tar /VOC2012trainval.tar

benchmark.targz 重命名为 berkeleyVoc12Segments.tar.gz

这里也可以选择直接运行fcnTrain,Matlab会自己下载,只是担心官网下载速度慢,发现使用迅雷下载速度会更快,于是建议自己下载两个数据压缩包,然后重命名,放入对应文件夹下,运行脚本时会自动检查数据并解压到对应目录。

3.2 预训练模型

如果你不想训练自己的模型,直接使用预训练好的模型(这也是MatConvNet最方便的一点),那么直接下载预训练好的模型放到./data/models/目录下即可。

4.调试训练

这一步也是最麻烦的,因为每个人遇到的问题都可能不同,所以多半时候需要自己debug,这里只提供一些个人经验了,如果有补充可以在评论区进行回复,博主可以进一步完善。

4.1 运行调试

直接运行fcnTrain()函数,这是注意其中设置的路径是否与自己设置的路径对应,第一步就是其中的VOCSetup的两个函数,其中会对数据进行解压缩处理,保证配置正确,才能定位到数据。如果提示找不到数据,那么打断点调试,看看缺了哪些数据,这些数据是否可以不要。

博主使用Matlab2017a,Cuda8.0,cudnn,硬件平台是gtx1070,后面的问题和解决仅供参考,博主在调试过程中分别遇到如下问题:

问题1:getDatasetStatistics: computing segmentation stats for training image 1 报错

错误定位到:getDatasetStatistics.m 文件 Line 9

经过调试,下面这个地方,看出问题来了吧,这里把’\’替换成’\\’ 或者 ‘/’ 就可以了,否则文件是读不出来的

解决:将Line9处的代码替换为:

问题2:fcnTrain(line95) 错误代码 Reference to non-existent field ‘gpus’.

错误信息:

Error in fcnTrain (line 95)
bopts.useGpu = numel(opts.train.gpus) > 0 ;

错误信息是所,opts.train没有gpus字段,那么就要从opts.train查起了,经过调试发现整个opts.train都是空的,检查了下发现可能是需要在输入参数中进行设置?然后再github上直接找到了答案

解决:trainOpts 替换为opts.train 并将Line23 修改为 opts.train = [];

问题3:和问题1一样,字符串的问题,如下图

解决:定位错误到getbatch.m Line51, 替换成如下代码:

版本在不断更新,并且希望将自己的经验汇总贡献一篇教程,或者遇到了其它问题,可以在下方留言给博主。

开心的训练吧:

CPU:

直接成功

GPU:

需要再进行debug

1. 虽然编译了gpu版本的matconvnet,但是 opts.train.gpus 依然为空,最后使用的还是CPU,于是就到github去查了一下,迅速找到答案:opts.train.gpus = [1] ;

2. 然后又爆出错误:The CUDA error code was: CUDA_ERROR_ILLEGAL_ADDRESS. 继续Google,地址问题,轻松解决。

*18年2月8日补充:关于CUDA_ERROR_ILLEGAL_ADDRESS:

博主曾经采用CUDA8.0、VS2013和matconvnet-1.o-beta23测试成功(具体解决方法事后想不起来,太久远了,似乎是折腾了许久cudnn版本)

一旦牵扯到环境,问题通常都比较复(玄)杂(学),下面的引用是评论区马同学对各个环境进行的测试,最终使用GTX1070+win10调通fcn:

GTX 1070显卡 + windows10

一开始使用matconvnet-1.0-beta25.tar.gz + matlab2017b + CUDA8.0 会出现The CUDA error code was: CUDA_ERROR_ILLEGAL_ADDRESS的情况,
(1)在使用 CUDA8.0 时无论搭配哪种版本的 cudnn都无法解决这种问题,所以将CUDA8.0降为CUDA7.5,但是又会出现 Unsupported gpu architecture ‘compute_61’的情况,根据
http://blog.csdn.net/a1154761720/article/details/53395414 中的解决方法解决了。
(2)matconvnet-1.0-beta25.tar.gz编译GPU时只能用vs2015,vs2013不能使用,CUDA7.5编译又只能用vs2013.所以不能最新的matconvnet。
(3)CUDA8.0对应matlab2017,降低CUDA的版本,也就降低了matlab的版本,降为matlab2015
(4)最后的配置为
CUDA7.5 + matlab2015 + vs2013,可以直接下载别人编译好的文件
博客地址为 http://blog.csdn.net/zhjm07054115/article/details/51569450
视频以及代码的地址为 http://www.studyai.com/course/detail/64bf671f1ecf44ed9a8404a198604321

再次感谢马同学的测试和分享!

GTX1070超频到1860MHz之后,大约训练6个小时就可以出结果了,还是相当给力的。(博主训练一般就停了,6小时是根据同学训练的时间预估的)

4.2 预训练调试

上面搞定,这个就简单多了,使用预训练模型的方式有三种,根据fcnTest中的 switch case 发现三种分别是matconvnet、ModelZoo、TVG。

‘matconvnet’就是使用自己训练存储好的网络模型,以‘input’为起点

‘ModelZoo’就是使用Caffe的模型,这里我们发现目录中还有一个文件fcnTestModelZoo,如果使用matcaffe,那么可以从这个脚本开始。

‘TVG’是什么呢?我不清楚,它以’coarse’层结尾,而下载的模型是以upscore结尾的。

所以我们经过简单调试,发现需要修改的地方只有五个:

1. 修改modelPath为我们下载的模型文件

2. 修改modelFamily为 ‘TVG’

3. 修改‘TVG’结尾为‘upscore’(原先是‘coarse’),发现我们下载的模型并没有‘coarse’

4. 和训练时候一样的字符串文字,修改Line114为: labelsPath = sprintf(strrep(imdb.paths.classSegmentation, ‘\’, ‘\\’), name) ;

5. 如果使用gpu,单个GPU情况下,修改opts.gpus = [1]

结果存储在结果路径下面,重新运行如果不删除原先的结果文件,那么会直接显示结果而不会再训练,所以要删掉原先文件再训练。

如果要测试自己的数据,那么直接im = imread(…) 的地方修改就可以了,总之调通之后,自己看代码吧

测试

开心的运行demo吧

虽然训练时间很长,检测速度还是挺快的,检测时候大概需要3G显存

你可能感兴趣的:(MATCONVNET进行FCN语义分割)