deeplabv3+训练自己的数据集

deeplabv3+训练自己的数据集

 

环境:ubuntu 16.04 + TensorFlow 1.9.1 + cuda 9.0 + cudnn 7.0 +python3.6

tensorflow 项目链接 https://github.com/tensorflow/models.git (deeplabv3+)

1、添加依赖库到PYTHONPATH

首先添加slim路径,每次打开terminal都要加载路径

 
  1. # From tensorflow/models/research/

  2. export PYTHONPATH=$PYTHONPATH:`pwd`:`pwd`/slim

注意,运行后要将所以终端关闭,重启~

2、测试一下

快速测试,调用model_test.py:

 
  1. # From tensorflow/models/research/

  2. python deeplab/model_test.py

若出现ok,就成功啦

3、数据集的格式

简单来说,需要把数据预处理成规定的格式和尺寸范围,生成包含文件名的文本文件,最后以规定的目录形式组织起来。
数据的目录组织形式应当这样:

 
  1. + Database # 自己的数据集名称

  2. + JPEGImages

  3. + SegmentationClass

  4. + ImageSets

  5. + Segmentation

  6. - train.txt

  7. - val.txt

  8. - trainval.txt

  9. - test.txt

  10. + tfrecord

其中:

  • JPGImages 文件夹存放RGB图像;

  • SegmentationClass 存放转换为class的标签,格式为单通道的png图像,将数据值转化为对应目标类型(0,1,2,3……)。对应的图像和标签的文件名相同!!扩展名分别为.png.png

  • ImageSets/Segmentation 存放有图像文件名的 .txt 文件,这里我按文件名将数据分为 trainvaltrainval

  • tfrecord 存放转换的 tfrecord 格式的数据。

  • .txt 文件中的内容应当为对应图像的文件名,不带扩展名,如下所示:

 
  1. filename1

  2. filename2

  3. filename3

  4. .....

4、数据集转换为tfrecord格式

1、对于不大的数据集来说,tensorflow提供了一种高效率的数据读取模式,将数据转换为 TFRecord 格式。这里不多作解释,想要更深入的了解请寻它处。tensorflow读取数据-tfrecord格式

运行datasets中的build_voc2012_data.py,将数据集转换为tfrecord格式,修改参数

这里可以直接使用 datasets/build_voc2012_data.py 的代码。

 
  1. python build_voc2012_data.py --image_folder=./Database/JPEGImages \

  2. --semantic_segmentation_folder=./Database/SegmentationClass \

  3. --list_folder=./Database/ImageSets/Segmentation \

  4. --output_dir=./Database/tfrecord

     image_folder 图像位置

     semantic_segmentation_folder 标注位置(生成的mask)

     list_folder 列表位置(segmentation里的txt文件)

     output_dir 输出位置

可在代码中调节参数 _NUM_SHARDS (默认为4),改变数据分块的数目。(一些文件系统有最大单个文件大小的限制,如果数据集非常大,增加 _NUM_SHARDS 可减小单个文件的大小)。

5、训练

在DeepLabv3+模型的基础上,主要需要修改以下几个文件

  • segmentation_dataset.py文件
  • train_utils.py

注册数据集

距离开始训练我们的数据集仅一步之遥了,接下来注册我们的数据集,在 segmentation_dataset.py 文件中找到这段:

 
  1. _DATASETS_INFORMATION = {

  2. 'cityscapes': _CITYSCAPES_INFORMATION,

  3. 'pascal_voc_seg': _PASCAL_VOC_SEG_INFORMATION,

  4. 'ade20k': _ADE20K_INFORMATION,

  5. 'dataset_name': _DATASET_NAME, # 自己的数据集名字及对应配置放在这里

  6. }

然后添加数据集的相关配置,名字要和上面注册的数据集相同。

 
  1. _DATASET_NAME = DatasetDescriptor(

  2. splits_to_sizes={

  3. 'train': 10000,

  4. 'val': 2000, # 这里根据Segmentation中的.txt文件名对应,

  5. 'trainval': 12000 # 数字代表对应数据集包含图像的数量

  6. },

  7. num_classes=5, # 类别数目,包括背景

  8. ignore_label=255, # 有些数据集标注有白色描边(VOC 2012),不代表任何实际类别

  9. )

train_utils.py

对应的train_utils.py中,先将109行关于exclude_list的设置修改,作用是在使用预训练权重时候,不加载该logit层:

 
  1. # Variables that will not be restored.

  2. exclude_list = ['global_step','logits']

  3. if not initialize_last_layer:

  4. exclude_list.extend(last_layers)

commom.py中

将model_variant改为xception_65

 

训练和可视化

(1)训练(train.py)

参考aquariusjay在github上的解疑.

如果想在DeepLab的基础上fine-tune其他数据集, 可在train.py中修改输入参数。有一些选项:

  • 使用预训练的所有权重,设置initialize_last_layer=True
  • 只使用网络的backbone,设置initialize_last_layer=Falselast_layers_contain_logits_only=False
  • 使用所有的预训练权重,除了logits,因为如果是自己的数据集,对应的classes不同(这个我们前面已经设置不加载logits),可设置initialize_last_layer=Falselast_layers_contain_logits_only=True

最终,我的设置是:

  • initialize_last_layer=False   (把 True 改成 False ,重新训练最后一层。)
  • last_layers_contain_logits_only=True
  • training_number_of_steps设置为50000
  • crop_size缩小为321(由于内存不够,将其改小,但是crop_size至少要大于300,遵循的公式是(crop_size-1)/4为整数)
  • batch_size改到8
  •  
    1. python train.py \

    2. --logtostderr \

    3. --train_split="trainval" \ 可以选择train/val/trainval 不同的数据集

    4. --model_variant="xception_65" \

    5. --atrous_rates=6 \

    6. --atrous_rates=12 \

    7. --atrous_rates=18 \

    8. --output_stride=16 \

    9. --decoder_output_stride=4 \

    10. --train_crop_size=321 \

    11. --train_crop_size=321\

    12. --train_batch_size=8\

    13. --training_number_of_steps=50000 \

    14. --fine_tune_batch_norm=False \(由于batchsize小于12,将其改为false)

    15. --tf_initial_checkpoint="加载与训练模型/model.ckpt" \

    16. --train_logdir="保存训练的中间结果" \

    17. --dataset_dir="生成的tfrecord的路径"

    18.  

     

  • 参数设置注意事项:
 
  1.  
  2. # When fine_tune_batch_norm=True, use at least batch size larger than 12

  3. # (batch size more than 16 is better). Otherwise, one could use smaller batch

  4. # size and set fine_tune_batch_norm=False.

 
  1.  
  2. # For `xception_65`, use atrous_rates = [12, 24, 36] if output_stride = 8, or

  3. # rates = [6, 12, 18] if output_stride = 16. Note one could use different

(2)验证(eval.py)

eval.py中的相关参数设置:

 
  1. python eval.py \

  2. --logtostderr \

  3. --eval_split="val" \

  4. --model_variant="xception_65" \

  5. --atrous_rates=6 \

  6. --atrous_rates=12 \

  7. --atrous_rates=18 \

  8. --output_stride=16 \

  9. --decoder_output_stride=4 \

  10. --eval_crop_size=513 \

  11. --eval_crop_size=513 \

  12. --checkpoint_dir="${TRAIN_LOGDIR}" \

  13. --eval_logdir="${EVAL_LOGDIR}" \

  14. --dataset_dir="${DATASET}"

  15.  

输出miou,来评估模型的好坏。

loss的可视化


可一边训练一边可视化训练的 log,访问 http://localhost:6006/ 即可看到 loss 等的变化。

 
  1.  
  2. # From deeplab/datasets/rs/exp

  3.  
  4. tensorboard --logdir train/

可视化验证的 log,可看到 miou_1.0 的变化,这里指定了另一个端口。

 
  1.  
  2. # From deeplab/datasets/rs/exp/

  3.  
  4. tensorboard --logdir eval/ --port 6007

或同时可视化训练与验证的log:

 
  1.  
  2. # From deeplab/datasets/pascal_voc_seg/exp/train_on_train_set

  3.  
  4. tensorboard --logdir .

分割结果可视化

最后为了最后的分割结果可视化,也就是将输出的 class map 着色为 colored map 。需要在 get_dataset_colormap.py 文件中修改

 
  1. # Dataset names.

  2. _ADE20K = 'ade20k'

  3. _CITYSCAPES = 'cityscapes'

  4. _MAPILLARY_VISTAS = 'mapillary_vistas'

  5. _PASCAL = 'pascal'

  6. _DATASET_NAME='dataset_name' # 添加在这里,和注册的名字相同

  7.  
  8. # Max number of entries in the colormap for each dataset.

  9. _DATASET_MAX_ENTRIES = {

  10. _ADE20K: 151,

  11. _CITYSCAPES: 19,

  12. _MAPILLARY_VISTAS: 66,

  13. _PASCAL: 256,

  14. _DATASET_NAME: 151, # 在这里添加 colormap 的颜色数

  15. }

接下来写一个函数,用途是返回一个 np.ndarray 对象,尺寸为 [classes, 3] ,即colormap共有 classes 种RGB颜色,分别代表不同的类别。

这个函数具体怎么写,还是由数据集的实际情况来定,我的数据集提供了 colormap ,就直接返回就可以了,就像下面这样。

 
  1. def create_dataset_name_label_colormap():

  2. return np.asarray([

  3. [165, 42, 42],

  4. [0, 192, 0],

  5. [196, 196, 196],

  6. [190, 153, 153],

  7. [180, 165, 180],

  8. [102, 102, 156],

  9. [102, 102, 156],

  10. [128, 64, 255],

  11. ...

  12. ])

最后修改 create_label_colormap 函数,在这个调用接口中加上我们自己的数据集:

 
  1. def create_label_colormap(dataset=_PASCAL):

  2. """Creates a label colormap for the specified dataset.

  3.  
  4. Args:

  5. dataset: The colormap used in the dataset.

  6.  
  7. Returns:

  8. A numpy array of the dataset colormap.

  9.  
  10. Raises:

  11. ValueError: If the dataset is not supported.

  12. """

  13. if dataset == _ADE20K:

  14. return create_ade20k_label_colormap()

  15. elif dataset == _CITYSCAPES:

  16. return create_cityscapes_label_colormap()

  17. elif dataset == _MAPILLARY_VISTAS:

  18. return create_mapillary_vistas_label_colormap()

  19. elif dataset == _PASCAL:

  20. return create_pascal_label_colormap()

  21. elif dataset == _DATASET_NAME: # 添加在这里

  22. return create_dataset_name_label_colormap()

  23. else:

  24. raise ValueError('Unsupported dataset.')

验证集上的可视化

vis.py中的相关参数设置为:

  • vis_split:设置为val
  • vis_crop_size:设置513,513为真实图片的大小
  • dataset:设置为我们在segmentation_dataset.py文件设置的数据集名称
  • dataset_dir:设置为创建的TFRecord
  • colormap_type:可视化标注的颜色  (vis.py中的此处要改下)

vis.py有点问题

其他的注意点:

ignore_label 如果你的数据集存在ignore_label,注意不要把ignore_label和background混淆。 ignore_label是没有做标注的,不在预测范围内的,ignore_label是不参与计算loss的。我们在mask中将ignore_label的灰度值标记为255。

 

 

参考的文献:

https://blog.csdn.net/weixin_41713230/article/details/81937763#commentsedit

https://blog.csdn.net/u011974639/article/details/80948990

https://zhuanlan.zhihu.com/p/42756363

https://blog.csdn.net/qq_32799915/article/details/80070711#commentsedit

https://blog.csdn.net/Kelvin_XX/article/details/81946091

https://blog.csdn.net/ncloveqy/article/details/82285106

https://blog.csdn.net/qq_32799915/article/details/80070711

https://blog.csdn.net/u011974639/article/details/80948990

https://blog.csdn.net/weixin_41713230/article/details/81081120

https://blog.csdn.net/weixin_41713230/article/details/81076292(单通道)

https://blog.csdn.net/qq_17130909/article/details/82980542(单通道)

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值