如何使用ssd训练自己的数据

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用ssd训练自己的数据相关的知识,希望对你有一定的参考价值。

可以参照前一篇文章配置windows下的ssd,本文假设ssd已经通过windows下的编译。

1.准备数据

需要根据PASCAL VOC格式 准备对应的数据,推荐一个好用的贴标签软件(https://github.com/tzutalin/labelImg)

拿VOC2012为例,VOC2012目录下需要Annotations、ImageSets、JPEGImages文件夹,Annotations存储对应的标签xml信息,JPEGImages存储图片数据,ImageSets 主要使用Main文件夹下的数据,Main文件夹保存了对应的训练、验证数据集的txt文本

然后使用caffe-ssd-microsoft\data\VOC0712目录下create_data.bat来生成所需要的lmdb文件(create_data.bat根据实际情况修改内容)

caffe-ssd-microsoft\data\VOC0712目录下get_image_size.bat用于生成test.txt中对应图片的大小映射,生成的结果写入test_name_size.txt
对于后面的训练需要准备以下文件:

test.txt 用于测试的文件集定义
labelmap_voc.prototxt 标签定义文件
test_name_size.txt 测试图片大小定义文件(可通过get_image_size.bat生成)
trainval.txt 训练验证集文件定义(数据排列为乱序,可根据实际情况设定)

train.prototxt 训练网络定义文件
test.prototxt 测试网络定义文件
deploy.prototxt 部署定义文件
solver.prototxt 训练配置文件

2.修改训练文件

caffe-ssd-microsoft\examples\ssd下的ssd_pascal.bat是用来训练数据用的程序(它是调用ssd_pascal.py运行的,ssd_pascal.py用来配置整个的训练环境),因为windows下的对 路径和Linux的不同,所以对应的windows下需要找到ssd_pascal.py对应的内容进行修改:

train_data = "/data/VOC0712/trainval_lmdb".format(caffe_root)
test_data = "/data/VOC0712/test_lmdb".format(caffe_root)
save_dir = "/models/VGGNet/VOC0712/".format(caffe_root,job_name)
snapshot_dir = "/models/VGGNet/VOC0712/".format(caffe_root,job_name)
job_dir = "/jobs/VGGNet/VOC0712/".format(caffe_root,job_name)
output_result_dir = "/data/VOC0712/results//Main".format(caffe_root,job_name)
name_size_file = "/data/VOC0712/test_name_size.txt".format(caffe_root)
pretrain_model = "/models/VGGNet/VGG_ILSVRC_16_layers_fc_reduced.caffemodel".format(caffe_root)
label_map_file = "/data/VOC0712/labelmap_voc.prototxt".format(caffe_root)
f.write('\Build\\Debug\caffe train ^\n'.format(caffe_root,'x64'))
参考技术A 让你再重新说一次

训练 SSD-Tensorflow 遇到的若干问题

根据开源代码SSD-Tensorflow,训练数据的时候遇到若干问题,记录如下。

遇到的第一个问题

这个bug 无关SSD-Tensorflow本身。

首先制作tfrecords格式的数据,使用教程上指令:

DATASET_DIR=./VOC2007/test/
OUTPUT_DIR=./tfrecords
python tf_convert_data.py     --dataset_name=pascalvoc     --dataset_dir=${DATASET_DIR}     --output_name=voc_2007_train     --output_dir=${OUTPUT_DIR}

按照教程上的,写了一个change.sh脚本文件,然后运行sh change.sh。报错如下:

[email protected]:~/SSD-Tensorflow$ sh change.sh 
Traceback (most recent call last):
  File "tf_convert_data.py", line 59, in <module>
    tf.app.run()
  File "/home/matthew/tensorflow_5/lib/python3.5/site-packages/tensorflow/python/platform/app.py", line 48, in run
    _sys.exit(main(_sys.argv[:1] + flags_passthrough))
  File "tf_convert_data.py", line 49, in main
    raise ValueError('You must supply the dataset directory with --dataset_dir')
ValueError: You must supply the dataset directory with --dataset_dir
change.sh: 4: change.sh: --dataset_name=pascalvoc: not found
: not found5: change.sh: --dataset_dir=./VOC2007/test/
change.sh: 6: change.sh: --output_name=voc_2007_train: not found
: not found7: change.sh: --output_dir=./tfrecords

这个不是脚本代码本身的错误,而是因为操作系统缘故。我本地电脑的无GPU (穷啊唉~),用的是windows系统,然后将代码上传到服务器的ubuntu系统上执行。

windows的默认换行是 ,而linux的换行是 linux命令的续行符号后面是不允许添加除换行以外符号的,空格都不允许。

所以上面的报错主要原因是换行符号。解决方法如下:

sed -i 's/
$//g'  change.sh

使用sed流编辑命令,将change.sh每个行末的 替换成为空。

遇到的第二个问题

在完成数据文件tfrecords制作之后,按照指令运行train_ssd_network.py。成功运行代码几秒后,报错如下:

INFO:tensorflow:Error reported to Coordinator: <class 'tensorflow.python.framework.errors_impl.InvalidArgumentError'>, All bounding box coordinates must be in [0.0, 1.0]: 1.002
     [[Node: ssd_preprocessing_train/distorted_bounding_box_crop/sample_distorted_bounding_box/SampleDistortedBoundingBoxV2 = SampleDistortedBoundingBoxV2[T=DT_INT32, area_range=[0.1, 1], aspect_ratio_range=[0.6, 1.67], max_attempts=200, seed=0, seed2=0, use_image_if_no_bounding_boxes=true, _device="/job:localhost/replica:0/task:0/device:CPU:0"](ssd_preprocessing_train/distorted_bounding_box_crop/Shape, ssd_preprocessing_train/distorted_bounding_box_crop/ExpandDims, ssd_preprocessing_train/distorted_bounding_box_crop/sample_distorted_bounding_box/SampleDistortedBoundingBoxV2/min_object_covered)]]
INFO:tensorflow:Finished training! Saving model to disk.
Traceback (most recent call last):
  File "train_ssd_network.py", line 390, in <module>
    tf.app.run()
  File "/home/matthew/tensorflow_5/lib/python3.5/site-packages/tensorflow/python/platform/app.py", line 48, in run
    _sys.exit(main(_sys.argv[:1] + flags_passthrough))
  File "train_ssd_network.py", line 386, in main
    sync_optimizer=None)
  File "/home/matthew/tensorflow_5/lib/python3.5/site-packages/tensorflow/contrib/slim/python/slim/learning.py", line 775, in train
    sv.stop(threads, close_summary_writer=True)
  File "/home/matthew/tensorflow_5/lib/python3.5/site-packages/tensorflow/python/training/supervisor.py", line 792, in stop
    stop_grace_period_secs=self._stop_grace_secs)
  File "/home/matthew/tensorflow_5/lib/python3.5/site-packages/tensorflow/python/training/coordinator.py", line 389, in join
    six.reraise(*self._exc_info_to_raise)
  File "/usr/lib/python3/dist-packages/six.py", line 686, in reraise
    raise value
  File "/home/matthew/tensorflow_5/lib/python3.5/site-packages/tensorflow/python/training/queue_runner_impl.py", line 238, in _run
    enqueue_callable()
  File "/home/matthew/tensorflow_5/lib/python3.5/site-packages/tensorflow/python/client/session.py", line 1231, in _single_operation_run
    target_list_as_strings, status, None)
  File "/home/matthew/tensorflow_5/lib/python3.5/site-packages/tensorflow/python/framework/errors_impl.py", line 473, in __exit__
    c_api.TF_GetCode(self.status.status))
tensorflow.python.framework.errors_impl.InvalidArgumentError: All bounding box coordinates must be in [0.0, 1.0]: 1.002
     [[Node: ssd_preprocessing_train/distorted_bounding_box_crop/sample_distorted_bounding_box/SampleDistortedBoundingBoxV2 = SampleDistortedBoundingBoxV2[T=DT_INT32, area_range=[0.1, 1], aspect_ratio_range=[0.6, 1.67], max_attempts=200, seed=0, seed2=0, use_image_if_no_bounding_boxes=true, _device="/job:localhost/replica:0/task:0/device:CPU:0"](ssd_preprocessing_train/distorted_bounding_box_crop/Shape, ssd_preprocessing_train/distorted_bounding_box_crop/ExpandDims, ssd_preprocessing_train/distorted_bounding_box_crop/sample_distorted_bounding_box/SampleDistortedBoundingBoxV2/min_object_covered)]]

问题的主要原因是:

数据集中的数据标记不规范,出现了bbox四个坐标值落到到图像外的情况。

提供两条解决思路:

  • 写脚本,判断出有哪些图片标记出错了。然后,删除这些标记不规范的图片,重新制作数据集。
  • 修改tfrecords制作过程。

首先,第一个方法是可行的,就是比较麻烦,要找到原来的图片,删除,重新制作成tfrecord格式。我写了一个简单的脚本,检查之后发现,我使用的数据集(1W张图片)中有200+图片标记有问题,都是xmaxymax超出了边界几个像素。

一些原因(嗯嗯嗯,主要是懒,2333),我不想再制作一遍数据集。决定找个相对优雅的方法解决这个问题。于是就有了第二个方案:

追踪tf_convert_data.py,发现主要使用datasets/pascalvoc_to_tfrecords.py执行数据格式转化工作。找到114-119行:

bboxes.append((float(bbox.find('ymin').text) / shape[0],
                       float(bbox.find('xmin').text) / shape[1],
                       float(bbox.find('ymax').text) / shape[0],
                       float(bbox.find('xmax').text) / shape[1]
                       ))

修改为:

bboxes.append((max(float(bbox.find('ymin').text) / shape[0], 0.0),
                       max(float(bbox.find('xmin').text) / shape[1], 0.0),
                       min(float(bbox.find('ymax').text) / shape[0], 1.0),
                       min(float(bbox.find('xmax').text) / shape[1], 1.0)
                       ))

然后使用命令,重新将数据集制作成tfrecords格式,问题便解决了。

这样做是合理的,理由如下:

标记员将坐标标记错误,跳出了图像范围,这时候识别目标应该就在图像边缘,所以选取图像边界作为目标的边界是合理的。

主要参考链接

https://github.com/balancap/SSD-Tensorflow/issues/37

https://blog.csdn.net/lin_bingfeng/article/details/53750516

写作不易,尊重原创,喜欢请点赞,评论,打赏~

以上是关于如何使用ssd训练自己的数据的主要内容,如果未能解决你的问题,请参考以下文章

训练SSD后如何预测Precision、Recall和F1分数

Caffe上用SSD训练和测试自己的数据

SSD-Pytorch训练自己的VOC数据集&遇到的问题及解决办法

caffe_ssd学习-用自己的数据做训练

目标检测算法SSD在window环境下GPU配置训练自己的数据集

人工智能神经网络不训练检测模型,如何进行对象的检测与追踪?