赞
踩
首先贴一下参考链接,并对这些文章的作者表示由衷的感谢!
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.
因为我自身比较菜,遇到很多很多非常基础的问题,在这里我把运行的整个过程和所遇到的所有问题全都记录下来,尽管有些是很低级的错误,但是多写一些说不定哪天就能对别人有用了,希望能对其他人有所帮助。
首先在git上下载Deeplab v3+的源码,地址https://github.com/tensorflow/models/tree/master/research/deeplab,注意需要把上级目录research下的slim也下载下来,用于支持代码中tensorflow的轻量代码。
之前在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)
把源码下载下来之后首先测试一下,看看deeplab有没有成功的安装。
activate激活tf环境,在 tensorflow/models/research/目录下执行
python deeplab/model_test.py
报错,找不到名为deeplab的模块,原因是没有定义slim的环境变量。
还是在该目录下,按照官方的引导,执行
export PYTHONPATH=$PYTHONPATH:`pwd`:`pwd`/slim
问题解决。再次运行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到底是个什么东西,还是不清楚。
算了,先不管他,既然运行通了一个,那就继续吧,而且也没有很多人提问这个问题,应该不是什么大问题,下面走不通的话再说。
对于我的问题,我不想要在别人的数据集上进行分割任务,我想在自己做的数据集上进行,那就需要进行下面这两步的准备工作。
首先,制作一个自己的数据集,需要满足指定的格式;
然后,让deeplab认可它。
我的数据集非常简单,就一类目标,所以数据集的制作和注册过程并不复杂。
在这里我先把所有的图片批量resize到了统一的大小。
介绍两种标注数据集的制作工具。
第一种是labelme,直接conda install,使用的时候直接在cmd里边敲labelme,然后就会弹出来界面,直接用就可以了,非常简单,属于不看介绍都会用的那种。它的保存格式是json。
第二种是标注精灵助手,也是一个非常好用的工具,直接百度一下下载,界面友好。我一开始选择了标注精灵,但是后来在训练的时候数据读入出了问题,所以还是建议大家使用labelme进行标注,标注完了之后需要对数据进行转换,将json转换成png,这个并不难,可以自行百度。
这里我主要参考了博客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
接下来要做的是转换成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' # 输出文件夹
我的理解是,注册就是把自己的数据集添加到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, # 刚才在上面新加的数据集名称 }
但是在train的时候,仍然报了错误,The specified dataset is not supported yet,说明还是没有注册成功,查了一下说有的版本需要在data_generator.py也操作一下。之后就可以了,注册的方法和segmentation_dataset.py中是一样的。其实看报错的是哪个脚本就可以发现自己的deeplab是用了哪个脚本去注册。
所以以后在注册数据集的时候关注data_generator.py就好了。
(注意,下面的代码有点问题,直接运行报错)
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'
报错
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。
很简单,参数的传入应该是宽高两个元素的字符串,我是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'
再次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.
简而言之,如果你是在做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)
那么恭喜你,训练已经开始了。
眼看就要训练完了,为了复制这段贴到博客,我在终端里习惯性的按了ctrl+C,心态崩了。。。
按理说这一部分应该先介绍,但是我急于求成,先把代码跑通,再回过头来看具体的含义,以便接下来的调参工作。下面截取了一部分FLAG:
FLAG | 含义 | Default |
---|---|---|
train_logdir | checkpoint等文件的保存路径 | None |
log_steps | 每隔多少step显示日志信息 | 10 |
save_interval_secs | 将模型写入磁盘的频率/sec | 1200 |
save_summaries_secs | 保存summary的频率/sec | 600 |
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 |
momentum | momentum超参数 | 0.9 |
adam_learning_rate | adam学习率 | 0.001 |
adam_epsilon | adam超参数epsilon | le-08 |
train_batch_size | 批大小 | 8 |
weight_decay | 权重衰减 | 0.00004 |
train_crop_size | 图片裁剪的大小 | ‘513,513’ |
tf_initial_checkpoint | 初始的checkpoint | None |
slow_start_learning_rate | 学习率慢启动的初始 | 1e-4 |
fine_tune_batch_norm | 是否对BN层的参数进行ne_tune | True |
min_scale_factor | 数据增强尺度缩放时的最小缩放比 | 0.5 |
max_scale_factor | 数据增强尺度缩放时的最大缩放比 | 2 |
atrous_rates | deeplab算法参数,池化的孔率 | None |
output_stride | 输入层到输出层,特征图缩小的比例 | 16 |
dataset | 数据集的名称 | pascal_voc_seg |
dataset_dir | 数据集的路径 | None |
在执行代码之前同样要在vis.py中加入指定GPU,不然还是会报cudnn的错
import os
os.environ['CUDA_VISIBLE_DEVICES'] = '/gpu:0'
然后在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'
开始运行的提示信息如下:
可视化的结果会保存在vis_logdir路径下。
同样的,先在代码里指定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'
报错
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]
参考博客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
再次执行,再次报错:
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)
是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
这个是因为反向传播的过程中图片的大小出错。如果遇到这个问题,一般是图片的size没有设置好,需要仔细检查一下。
到这里,利用的deeplab训练自己的数据,基本步骤就已经掌握了,接下来就是漫长的调参工作,以及对源码网络结构尝试进行修改。
如果你在训练过程中,遇到了本文没有提及到的问题,欢迎在下面留言,但是我可以很负责任的讲,我是新手!我也不会!
真的遇到解决不了的问题,第一好好再学一下tensorflow,补补基础,第二认真去看deeplab的源码,源码的注解写的非常清楚。
最后,如果本文对你有所帮助的话,记得点赞、投币、收藏,一键三连支持一下。那么我们下期再见。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。