FCN 实战

FCN 8s-Caffe-VOC 复现

1. 环境配置

2. 数据集说明

注意: VOC2012 验证集与 SBD 训练集有交叉的部分。

模型数据集

3. 更改模型路径

模型目录:

fcn.berkeleyvision.org/voc-fcn8s
    |_caffemodel-url        预训练权重的下载地址
    |_deploy.prototxt
    |_net.py                生成网络模型的文件,暂用不到
    |_solve.py
    |_solver.prototxt
    |_train.prototxt
    |_val.prototxt

将 fcn.berkeleyvision.org/data/pascal 文件下的 seg11valid.txt 拷贝到 VOC2012/ImageSets/Segmentation 文件夹下

~ solve.py

# -*- coding: UTF-8 -*-
+ import sys
+ sys.path.insert(0, '${caffe-root}/python')    # caffe python 接口
+ sys.path.append('fcn.berkeleyvision.org') # 把 FCN 模型加入 python 路径
...
* weights = './voc-fcn8s/VGG_ILSVRC_16_layers.caffemodel' # 下载好的预训练权重路径
...
- caffe.set_device(int(sys.argv[1]))
+ caffe.set_device(2) # 设置使用的gpu
...
* solver = caffe.SGDSolver('./voc-fcn8s/solver.prototxt')
...
* val = np.loadtxt('../data/pascal/seg11valid.txt', dtype=str)

~ solver.prototxt

* train_net: "./voc-fcn8s/train.prototxt"
* test_net: "./voc-fcn8s/val.prototxt"
...
* snapshot_prefix: "./voc-fcn8s/snapshot/train" # 先创建该目录

~ train.prototxt

* param_str: "{\'sbdd_dir\': \'./data/sbdd/dataset\',...

~ val.prototxt

* param_str: "{\'voc_dir\': \'../VOCdevkit/VOC2012\',...

数据层为自定义的Python Layer

4. 训练模型

在 fcn.berkeleyvision.org 文件夹下

$ python voc-fcn8s/solve.py 2>&1|tee /home/xieqi/workspace/caffe-fcn/voc-fcn8s/log/train-log-1.log

在 1080Ti 11g 上训练每秒大概能迭代 6.5 次,GPU 大约占用 5G。但训练开始的时候 loss 抖动的很严重,训练了 28000 次还是抖动的很严重,跟开始的时候没有区别,不收敛。停止训练,查找原因。

不收敛的原因分析:

解决不收敛的方法:

先把预训练模型加载到 VGG16 的网络中,再使用 FCN 提供的函数sugery.transplant(solver.net, vgg_net) 将全连接层的权值转化为卷积层的权值。

解决不收敛的过程:

  1. 下载 VGG_ILSVRC_16_layers_deploy.prototxt 文件。
  2. 修改 solver.py 文件。

~ solver.py

#!/home/xieqi/anaconda2/envs/py2.7/bin/python
# -*- coding: UTF-8 -*-

import sys
sys.path.insert(0, '/home/xieqi/workspace/caffe/python')
sys.path.append('/home/xieqi/workspace/caffe-fcn')

import caffe
import surgery, score

import numpy as np
import os

try:
    import setproctitle
    setproctitle.setproctitle(os.path.basename(os.getcwd()))
except:
    pass

vgg_weights ='../../VGG16/VGG_ILSVRC_16_layers.caffemodel'      # 增加
vgg_proto = '../../VGG16/VGG_ILSVRC_16_layers_deploy.prototxt'  # 增加

# weights = '/home/xieqi/workspace/caffe-fcn/voc-fcn8s/VGG_ILSVRC_16_layers.caffemodel'  # 注释掉

# init
# caffe.set_device(int(sys.argv[1]))
caffe.set_device(2)
caffe.set_mode_gpu()

solver = caffe.SGDSolver('/home/xieqi/workspace/caffe-fcn/voc-fcn8s/solver.prototxt')
# solver.net.copy_from(weights)                                 # 注释掉

vgg_net = caffe.Net(vgg_proto, vgg_weights, caffe.TRAIN)        # 增加
surgery.transplant(solver.net, vgg_net)                         # 增加
del vgg_net                                                     # 增加

# surgeries
interp_layers = [k for k in solver.net.params.keys() if 'up' in k]
surgery.interp(solver.net, interp_layers)

# scoring
val = np.loadtxt('/home/xieqi/workspace/caffe-fcn/data/pascal/seg11valid.txt', dtype=str)

for _ in range(25):
    solver.step(4000)
    score.seg_tests(solver, False, val, layer='score')

5. 测试模型

测试模型需要的文件

通过 train.prototxt 文件修改,修改内容。

~ 修改输入层

layer {
  name: "input"
  type: "Input"
  top: "data"

  input_param {
    # These dimensions are purely for sake of example;
    # see infer.py for how to reshape the net to the given input size.
    shape { dim: 1 dim: 3 dim: 500 dim: 500 }
  }
}
Table of Contents