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都要加载路径

# From tensorflow/models/research/
export PYTHONPATH=$PYTHONPATH:`pwd`:`pwd`/slim

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

2、测试一下

快速测试,调用model_test.py:

# From tensorflow/models/research/
python deeplab/model_test.py

若出现ok,就成功啦

3、数据集的格式

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

 + Database  # 自己的数据集名称
    + JPEGImages
    + SegmentationClass
    + ImageSets
        + Segmentation
            - train.txt
            - val.txt
            - trainval.txt
            - test.txt
 + tfrecord

其中:

  • JPGImages 文件夹存放RGB图像;

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

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

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

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

filename1
filename2
filename3
.....

4、数据集转换为tfrecord格式

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

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

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

python build_voc2012_data.py --image_folder=./Database/JPEGImages \
                             --semantic_segmentation_folder=./Database/SegmentationClass \
                             --list_folder=./Database/ImageSets/Segmentation \ 
                             --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 文件中找到这段:

_DATASETS_INFORMATION = { 
    'cityscapes': _CITYSCAPES_INFORMATION, 
    'pascal_voc_seg': _PASCAL_VOC_SEG_INFORMATION, 
    'ade20k': _ADE20K_INFORMATION, 
    'dataset_name': _DATASET_NAME,   # 自己的数据集名字及对应配置放在这里
}

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

_DATASET_NAME = DatasetDescriptor( 
    splits_to_sizes={ 
        'train': 10000, 
        'val': 2000,         # 这里根据Segmentation中的.txt文件名对应,
        'trainval': 12000    # 数字代表对应数据集包含图像的数量
    }, 
    num_classes=5,   # 类别数目,包括背景
    ignore_label=255,   # 有些数据集标注有白色描边(VOC 2012),不代表任何实际类别
)

train_utils.py

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

# Variables that will not be restored.
exclude_list = ['global_step','logits']
if not initialize_last_layer:
exclude_list.extend(last_layers)

commom.py中

将mobilenet_v2改为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=True  
  • last_layers_contain_logits_only=False
  • training_number_of_steps设置为50000
  • crop_size缩小为321(由于内存不够,将其改小,但是crop_size至少要大于300,遵循的公式是(crop_size-1)/4为整数)
  • batch_size改到8
  • python train.py \
      --logtostderr \
      --train_split="trainval" \  可以选择train/val/trainval 不同的数据集 
      --model_variant="xception_65" \
      --atrous_rates=6 \
      --atrous_rates=12 \
      --atrous_rates=18 \
      --output_stride=16 \
      --decoder_output_stride=4 \
      --train_crop_size=321 \
      --train_crop_size=321\
      --train_batch_size=8\
      --training_number_of_steps=50000 \
      --fine_tune_batch_norm=False \(由于batchsize小于12,将其改为false)
      --tf_initial_checkpoint="加载与训练模型/model.ckpt" \
      --train_logdir="保存训练的中间结果" \
      --dataset_dir="生成的tfrecord的路径"
    
    

     

  • 参数设置注意事项:

    # 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.

    # For `xception_65`, use atrous_rates = [12, 24, 36] if output_stride = 8, or
    # rates = [6, 12, 18] if output_stride = 16. Note one could use different

(2)验证(eval.py)

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

python eval.py \
  --logtostderr \
  --eval_split="val" \
  --model_variant="xception_65" \
  --atrous_rates=6 \
  --atrous_rates=12 \
  --atrous_rates=18 \
  --output_stride=16 \
  --decoder_output_stride=4 \
  --eval_crop_size=513 \
  --eval_crop_size=513 \
  --checkpoint_dir="${TRAIN_LOGDIR}" \
  --eval_logdir="${EVAL_LOGDIR}" \
  --dataset_dir="${DATASET}" 

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

loss的可视化


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


# From deeplab/datasets/rs/exp

tensorboard --logdir train/

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

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


# From deeplab/datasets/pascal_voc_seg/exp/train_on_train_set

tensorboard --logdir .

分割结果可视化

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

# Dataset names. 
_ADE20K = 'ade20k' 
_CITYSCAPES = 'cityscapes' 
_MAPILLARY_VISTAS = 'mapillary_vistas' 
_PASCAL = 'pascal' 
_DATASET_NAME='dataset_name'   # 添加在这里,和注册的名字相同

# Max number of entries in the colormap for each dataset. 
_DATASET_MAX_ENTRIES = { 
    _ADE20K: 151, 
    _CITYSCAPES: 19, 
    _MAPILLARY_VISTAS: 66, 
    _PASCAL: 256, 
    _DATASET_NAME: 151,   # 在这里添加 colormap 的颜色数
}

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

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

def create_dataset_name_label_colormap(): 
     return np.asarray([ 
        [165, 42, 42],
        [0, 192, 0],
        [196, 196, 196],
        [190, 153, 153],
        [180, 165, 180],
        [102, 102, 156],
        [102, 102, 156],
        [128, 64, 255],
        ...
        ])

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

def create_label_colormap(dataset=_PASCAL): 
  """Creates a label colormap for the specified dataset. 

  Args: 
    dataset: The colormap used in the dataset. 

  Returns: 
    A numpy array of the dataset colormap. 

  Raises: 
    ValueError: If the dataset is not supported. 
  """ 
  if dataset == _ADE20K: 
    return create_ade20k_label_colormap() 
  elif dataset == _CITYSCAPES: 
    return create_cityscapes_label_colormap() 
  elif dataset == _MAPILLARY_VISTAS: 
    return create_mapillary_vistas_label_colormap() 
  elif dataset == _PASCAL: 
    return create_pascal_label_colormap() 
  elif dataset == _DATASET_NAME:             # 添加在这里
    return create_dataset_name_label_colormap()
  else:
    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(单通道)

 

  • 10
    点赞
  • 72
    收藏
    觉得还不错? 一键收藏
  • 55
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 55
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值