当前位置:   article > 正文

超详细!Deeplab v3+ 源码运行记录,从环境配置到创建自己的数据集再到完成训练_deeplab代码运行

deeplab代码运行

0 感谢

首先贴一下参考链接,并对这些文章的作者表示由衷的感谢!

https://blog.csdn.net/jairana/article/details/83900226#42_train_333.
https://blog.csdn.net/jiangchuanhu/article/details/94381622.
https://blog.csdn.net/vagrantabc2017/article/details/77507168.
https://www.cnblogs.com/wj-1314/p/11211333.html.
https://blog.csdn.net/u013249853/article/details/96875325.
https://blog.csdn.net/weixin_43832437/article/details/84931184.
https://blog.csdn.net/weixin_38385446/article/details/82781109.
https://blog.csdn.net/qq_36685744/article/details/85843257.

因为我自身比较菜,遇到很多很多非常基础的问题,在这里我把运行的整个过程和所遇到的所有问题全都记录下来,尽管有些是很低级的错误,但是多写一些说不定哪天就能对别人有用了,希望能对其他人有所帮助。

1 源码下载与环境配置

1.1 源码下载

首先在git上下载Deeplab v3+的源码,地址https://github.com/tensorflow/models/tree/master/research/deeplab,注意需要把上级目录research下的slim也下载下来,用于支持代码中tensorflow的轻量代码。

1.2 环境配置

之前在windows里尝试操作,遇到各种问题,包括gitbash遇到没有权限的问题,还有tensorboard不好用等,所以干脆决定装ubuntu的双系统。其间经过了好几次驱动安装失败之后,然后重装系统,又失败,又重装,重复了好多次。
最后是ubuntu18.04 + GTX1660 ti显卡 + Nvidia 430驱动 + CUDA10.0,终于把驱动装好了。
(尽管1660ti目前推荐的驱动是440,但是经过两次驱动安装失败,又重装系统之后,还是决定装430,实践证明430是可以的)
然后用conda新建一个tensorflow的环境,conda install tensorflow-gpu=1.12(因为看网上有人用1.12的版本,我就也试一下1.12)

1.3 测试环境

把源码下载下来之后首先测试一下,看看deeplab有没有成功的安装。
activate激活tf环境,在 tensorflow/models/research/目录下执行

python deeplab/model_test.py
  • 1

报错,找不到名为deeplab的模块,原因是没有定义slim的环境变量。
还是在该目录下,按照官方的引导,执行

export PYTHONPATH=$PYTHONPATH:`pwd`:`pwd`/slim
  • 1

问题解决。再次运行model_test.py,又报错AttributeError: module ‘tensorflow._api.v1.compat’ has no attribute ‘v2’,造成报错的原因很简单,稍微熟悉tensorflow的同学就能看出来这是tf版本升级造成的,要在代码里边做一些修改,有些人说直接在import的的时候修改,但是我还是避免这样做,因为觉得麻烦,真要是每一处去改,可能比较费劲儿,而且搞不好漏下哪个地方,或者改错了,又增加一些麻烦。
对一个非常懒的人来说,改代码不如换环境,既然代码是tensorflow写的,那肯定有版本适用,那就去试呗,反正新建环境也用不了很多时间。分别试了2.0, 1.13, 1.11,都报了诸如此类的错误,最后在1.14的时候,没有报这个错误。
运行结果:
其实我也不确定这个结果是不是测试成功了,因为也没有看到过别人运行成功的图
但是运行第二个测试脚本的时候又出了问题,报错如下:absl.flags._exceptions.Error: Missing value for flag -v
网上差了一下也没查到相关的内容,看了一下报错的信息,猜测应该又是tensorflow内部的问题,似乎是在解析命令行参数的时候少了一个参数v的值,但是这个参数v到底是个什么东西,还是不清楚。
算了,先不管他,既然运行通了一个,那就继续吧,而且也没有很多人提问这个问题,应该不是什么大问题,下面走不通的话再说。

2 数据集的制作与注册

对于我的问题,我不想要在别人的数据集上进行分割任务,我想在自己做的数据集上进行,那就需要进行下面这两步的准备工作。
首先,制作一个自己的数据集,需要满足指定的格式;
然后,让deeplab认可它。
我的数据集非常简单,就一类目标,所以数据集的制作和注册过程并不复杂。

2.1 数据标注

在这里我先把所有的图片批量resize到了统一的大小。
介绍两种标注数据集的制作工具。
第一种是labelme,直接conda install,使用的时候直接在cmd里边敲labelme,然后就会弹出来界面,直接用就可以了,非常简单,属于不看介绍都会用的那种。它的保存格式是json。

第二种是标注精灵助手,也是一个非常好用的工具,直接百度一下下载,界面友好。我一开始选择了标注精灵,但是后来在训练的时候数据读入出了问题,所以还是建议大家使用labelme进行标注,标注完了之后需要对数据进行转换,将json转换成png,这个并不难,可以自行百度。

2.2 建立目录

这里我主要参考了博客https://blog.csdn.net/jairana/article/details/83900226#42_train_333,在此感谢原文博主。我的目录结构也用了相似的命名方法。
(其实你给他起什么名字无所谓的,照搬VOC的名字也行,只要结构正确就可以)
目录结构是这样的:

#  当前目录......./research/deeplab/datasets/seg/
    + image                     # 存放jpeg格式的原图
    + mask                      # 存放png格式的label图
    + index                     # 存放用于训练和测试的名单
        - train.txt                   # 用于训练的图片名单(一行一个,不加后缀)
        - val.txt                     # 用于测试的图片名单(同上)
        - trainval.txt                # 用于训练和测试的所有图片名单(同上)
    + tfrecord                  # 新建的文件夹,用于存放接下来生成的tfrecord
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

2.3 格式转换

接下来要做的是转换成TFRecord格式,这种格式方便图片的传入,至于为什么,感兴趣的同学可以参考这篇博客,介绍的非常详细:https://www.cnblogs.com/wj-1314/p/11211333.html
在这里不熟悉这个格式并不影响我们使用deeplab,官方源码提供了批量生成TFRecord的脚本build_voc2012_data.py,利用这个脚本去制作就可以了。

    python deeplab/datasets/build_voc2012_data.py \
      --image_folder='/home/chang/PycharmProjects/deeplab_test/models-master/research/deeplab/datasets/seg/image'   \  # 图片所在文件夹
      --semantic_segmentation_folder='/home/chang/PycharmProjects/deeplab_test/models-master/research/deeplab/datasets/seg/mask' \  # 标签png所在文件夹
      --list_folder='/home/chang/PycharmProjects/deeplab_test/models-master/research/deeplab/datasets/seg/index' \  # 存放训练测试list的文件夹
      --image_format='jpeg' \      # 图片格式,jpeg而不是jpg
      --output_dir='/home/chang/PycharmProjects/deeplab_test/models-master/research/deeplab/datasets/seg/tfrecord'   # 输出文件夹
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

2.4 数据集的注册

我的理解是,注册就是把自己的数据集添加到deeplab认可的数据库里,让它知道这个数据集的一些基本信息,比如,这个数据集叫什么名字,一共有多少张,一共有多少类。
参考别人的博客,对segmentation_dataset.py中的内容进行修改

# 在第100行左右加入新的数据集描述
_My_data = DatasetDescriptor(
    splits_to_sizes={
        'train': 100,   # 训练数
        'val': 30,       # 测试数
    },
    num_classes=2,   # 单目标,+1背景
    ignore_label=255,  # 忽略白边


# 修改120行左右的代码
_DATASETS_INFORMATION = {
    'cityscapes': _CITYSCAPES_INFORMATION,
    'pascal_voc_seg': _PASCAL_VOC_SEG_INFORMATION,
    'ade20k': _ADE20K_INFORMATION,
    'my_data': _My_data,  # 刚才在上面新加的数据集名称
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

但是在train的时候,仍然报了错误,The specified dataset is not supported yet,说明还是没有注册成功,查了一下说有的版本需要在data_generator.py也操作一下。之后就可以了,注册的方法和segmentation_dataset.py中是一样的。其实看报错的是哪个脚本就可以发现自己的deeplab是用了哪个脚本去注册。
报错信息所以以后在注册数据集的时候关注data_generator.py就好了。

3 训练自己的数据

3.1 开始训练

(注意,下面的代码有点问题,直接运行报错)

python deeplab/train.py \
--logtostderr \
--training_number_of_steps=3000 \
--model_variant="xception_65" \
--train_split="train" \
--atrous_rates=6 \
--atrous_rates=12 \
--atrous_rates=18 \
--output_stride=16 \
--decoder_output_stride=4 \
--train_crop_size=512 \
--train_batch_size=16 \
--dataset='my_data' \
--train_logdir='/home/chang/Desktop/logs' \
--dataset_dir='/home/chang/PycharmProjects/deeplab_test/models-master/research/deeplab/datasets/seg/tfrecord'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

报错
File “/home/chang/PycharmProjects/deeplab_test/models-master/research/deeplab/datasets/data_generator.py”, line 300, in _preprocess_image
crop_width=self.crop_size[1],
IndexError: list index out of range
很明显,是生成输入数据时出了问题,别着急,去找问题所在。通过报错信息发现,是train在创建Dataset类的时候出现了问题,而这个Dataset类是在data_generator.py中定义的,那就去里面找相应的crop_size。
上面说错了,这段代码是在train.py里面很简单,参数的传入应该是宽高两个元素的字符串,我是copy了别人的训练的指令,没有去看参数的说明,所以出了问题,这也提醒以后要细心。把–train_crop_size=512改成–train_crop_size=‘512,512’就可以了。

继续尝试,果然又报错了。
Unknown: Failed to get convolution algorithm. This is probably because cuDNN failed to initialize, so try looking to see if a warning log message was printed above.
是cuDNN的问题,这才意识到,配环境的时候nvcc -V成功之后就以为万事大吉了,竟然忘了装cuDNN,那就赶紧装呗。安装之后,再次运行,再次报了同样的错误,是因为在训练的时候没有指定显卡,于是,在train.py的开头加上下面的代码:

import os
os.environ['CUDA_VISIBLE_DEVICES'] = '/gpu:0'
  • 1
  • 2

再次train,成功开始训练。
如果出现如下情况
INFO:tensorflow:global_step/sec: 0
Killed
注意到train.py中有这样一段注解

# When fine_tune_batch_norm=True, use at least batch size larger than 12
# (batch size more than 16 is better). Otherwise, one could use smaller batch
# size and set fine_tune_batch_norm=False.
  • 1
  • 2
  • 3

简而言之,如果你是在做fine_tune的话,batch_size设置的大一些,否则,设置的小一些,至于为什么,我不清楚,先照做就是了。

如果cmd里出现了这样的代码:

INFO:tensorflow:global step 10: loss = 5.1319 (24.375 sec/step)
I0407 18:29:12.471430 140694608754496 learning.py:507] global step 10: loss = 5.1319 (24.375 sec/step)
  • 1
  • 2

那么恭喜你,训练已经开始了。
眼看就要训练完了,为了复制这段贴到博客,我在终端里习惯性的按了ctrl+C,心态崩了。。。

3.2 flags 说明

按理说这一部分应该先介绍,但是我急于求成,先把代码跑通,再回过头来看具体的含义,以便接下来的调参工作。下面截取了一部分FLAG:

FLAG含义Default
train_logdircheckpoint等文件的保存路径None
log_steps每隔多少step显示日志信息10
save_interval_secs将模型写入磁盘的频率/sec1200
save_summaries_secs保存summary的频率/sec600
optimizer优化器选择momentum
learning_policy学习率策略poly
base_learning_rate基础学习率0.0001
learning_rate_decay_factor学习率衰减率0.1
learning_rate_decay_step隔多少步衰减学习率2000
training_number_of_steps训练的step总数30000
momentummomentum超参数0.9
adam_learning_rateadam学习率0.001
adam_epsilonadam超参数epsilonle-08
train_batch_size批大小8
weight_decay权重衰减0.00004
train_crop_size图片裁剪的大小‘513,513’
tf_initial_checkpoint初始的checkpointNone
slow_start_learning_rate学习率慢启动的初始1e-4
fine_tune_batch_norm是否对BN层的参数进行ne_tuneTrue
min_scale_factor数据增强尺度缩放时的最小缩放比0.5
max_scale_factor数据增强尺度缩放时的最大缩放比2
atrous_ratesdeeplab算法参数,池化的孔率None
output_stride输入层到输出层,特征图缩小的比例16
dataset数据集的名称pascal_voc_seg
dataset_dir数据集的路径None

4 分割结果可视化

在执行代码之前同样要在vis.py中加入指定GPU,不然还是会报cudnn的错

import os
os.environ['CUDA_VISIBLE_DEVICES'] = '/gpu:0'
  • 1
  • 2

然后在cmd中执行

python deeplab/vis.py \
--logtostderr --vis_split="val"  \
--model_variant="xception_65" \
 --atrous_rates=6 \
 --atrous_rates=12 \
 --atrous_rates=18 \
 --outout_stride=16  \
 --decoder_output_stride=4 \
 --vis_crop_size="512,512" \ 
 --dataset="my_data"  \
 --colormap_type="pascal"  \
 --checkpoint_dir="/home/chang/Desktop/logs"  \
 --vis_logdir = '/home/chang/Desktop' \
 --dataset_dir='/home/chang/PycharmProjects/deeplab_test/models-master/research/deeplab/datasets/seg/tfrecord'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

开始运行的提示信息如下:
可视化运行结果可视化的结果会保存在vis_logdir路径下。

5 效果评估

同样的,先在代码里指定GPU,然后运行:

python deeplab/eval.py \
    --logtostderr \
    --eval_split="train" \
    --model_variant="xception_65" \
    --atrous_rates=6 \
    --atrous_rates=12 \
    --atrous_rates=18 \
    --output_stride=16 \
    --decoder_output_stride=4 \
    --eval_crop_size='512,512' \
    --dataset="my_data" \
    --checkpoint_dir="/home/chang/Desktop/logs"  \
    --eval_logdir = '/home/chang/Desktop' \
    --dataset_dir='/home/chang/PycharmProjects/deeplab_test/models-master/research/deeplab/datasets/seg/tfrecord'

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

报错

tensorflow.python.framework.errors_impl.InvalidArgumentError: assertion failed: 
[`labels` out of bound] [Condition x < y did not hold element-wise:] [x (mean_iou/confusion_matrix/control_dependency:0) = ] [0 0 0...] [y (mean_iou/Cast_1:0) = ] [2]
  • 1
  • 2

参考博客https://blog.csdn.net/qq_36685744/article/details/85843257,修改eval.py如下:

# 166行左右
    metric_map = {}
    # 加入下面这一段
    indices = tf.squeeze(tf.where(tf.less_equal(
        labels, dataset.num_of_classes - 1)), 1)
    labels = tf.cast(tf.gather(labels, indices), tf.int32)
    predictions = tf.gather(predictions, indices)
    # 结束
    num_classes = dataset.num_of_classes
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

再次执行,再次报错:

tensorflow.python.framework.errors_impl.InvalidArgumentError: Incompatible shapes: [262144] vs. [92409]
	 [[node false_negatives/Mul (defined at deeplab/eval.py:199) ]]

Errors may have originated from an input operation.
Input Source operations connected to node false_negatives/Mul:
 ToFloat (defined at deeplab/eval.py:151)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

是tensor的shape不一致,其中这个262144是我定义的输入是512*512,遇到这个问题,我猜测是由于数据没有成功的读进来,后来用labelme重新对数据进行了标注之后,问题就解决了。

再次执行,再次报错:

QUIRES failed at spacetobatch_op.cc:219 : Invalid argument: padded_shape[0]=56 is not divisible by block_shape[0]=12
2020-04-20 17:05:10.794013: W tensorflow/core/framework/op_kernel.cc:1502] OP_REQUIRES failed at spacetobatch_op.cc:219 : Invalid argument: padded_shape[0]=80 is not divisible by block_shape[0]=18
  • 1
  • 2

这个是因为反向传播的过程中图片的大小出错。如果遇到这个问题,一般是图片的size没有设置好,需要仔细检查一下。

结束

到这里,利用的deeplab训练自己的数据,基本步骤就已经掌握了,接下来就是漫长的调参工作,以及对源码网络结构尝试进行修改。
如果你在训练过程中,遇到了本文没有提及到的问题,欢迎在下面留言,但是我可以很负责任的讲,我是新手!我也不会!
真的遇到解决不了的问题,第一好好再学一下tensorflow,补补基础,第二认真去看deeplab的源码,源码的注解写的非常清楚。
最后,如果本文对你有所帮助的话,记得点赞、投币、收藏,一键三连支持一下。那么我们下期再见。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/454867
推荐阅读
相关标签
  

闽ICP备14008679号