tf版SSD训练自己的数据集--配置:TensorFlow-GPU1.2.0+python3.5.2+CUDA8.0

0.前言

本文主要记录自己在使用TensorFlow版SSD算法训练自己的数据集时的步骤。
我的文件夹具体内容如下图所示。这里只能显示文件夹,单独的文件无法显示。
在这里插入图片描述

1.数据集准备

数据集按照VOC的格式进行制作,图片标注的工具使用的是labelImg。数据集文件夹存放的方式需要稍作改变。具体格式如图片所示,文件夹分为test和train两个文件夹,Annotations文件夹放置的是对应的图片的标注信息,JPEGImages文件夹放置的是对应的图片。ImageSets文件夹中包含Main文件夹,test下的Main文件夹包括text.txt文件,train下的文件夹包括train.txt,val.txt,trainval.txt三个文件,但文件中的内容是一致的。同时还要在test和train文件夹下分别新建tfrecords文件夹,留作数据转换后存放文件使用。
在这里插入图片描述

2.数据格式转换

SSD算法在训练之前需要对数据格式进行转换。

  1. 首先要修改datdsets文件夹中pascalvoc_common.py文件,将其中的类别修改成自己数据集的类别。我的数据集是一个包括45类的车标数据集。
VOC_LABELS = {
   'none': (0, 'Background'),
   'BAIC GROUP': (1, 'BAIC GROUP'),
   'Ford': (2, 'Ford'),
   'SKODA': (3, 'SKODA'),
   'Venucia': (4, 'Venucia'),
   'HONDA': (5, 'HONDA'),
   'NISSAN': (6, 'NISSAN'),
   'Cadillac': (7, 'Cadillac'),
   'SUZUKI': (8, 'SUZUKI'),
   'GEELY': (9, 'GEELY'),
   'Porsche': (10, 'Porsche'),
   'Jeep': (11, 'Jeep'),
   'BAOJUN': (12, 'BAOJUN'),
   'ROEWE': (13, 'ROEWE'),
   'LINCOLN': (14, 'LINCOLN'),
   'TOYOTA': (15, 'TOYOTA'),
   'Buick': (16, 'Buick'),
   'Chery': (17, 'Chery'),
   'KIA': (18, 'KIA'),
   'HAVAL': (19, 'HAVAL'),
   'Audi': (20, 'Audi'),
   'LAND ROVER': (21, 'LAND ROVER'),
   'Volkswagen': (22, 'Volkswagen'),
   'Trumpchi': (23, 'Trumpchi'),
   'CHANGAN': (24, 'CHANGAN'),
   'Morris Garages': (25, 'Morris Garages'),
   'Renault': (26, 'Renault'),
   'LEXUS': (27, 'LEXUS'),
   'BMW': (28, 'BMW'),
   'MAZDA': (29, 'MAZDA'),
   'Mercedes-Benz': (30, 'Mercedes-Benz'),
   'HYUNDAI': (31, 'HYUNDAI'),
   'Chevrolet': (32, 'Chevrolet'),
   'BYD': (33, 'BYD'),
   'PEUGEOT': (34, 'PEUGEOT'),
   'Citroen': (35, 'Citroen'),
   'Huachen Auto Group': (36, 'Huachen Auto Group'),
   'Volvo': (37, 'Volvo'),
   'Mitsubishi': (38, 'Mitsubishi'),
   'Subaru': (39, 'Subaru'),
   'GMC': (40, 'GMC'),
   'Infiniti': (41, 'Infiniti'),
   'FAW Haima': (42, 'FAW Haima'),
   'SGMW': (43, 'SGMW'),
   'Soueast Motor': (44, 'Soueast Motor'),
   'QOROS': (45, 'QOROS'),
}
  1. 修改datasets文件夹下的pascalvoc_to_records.py文件,更改83行的读取方式为‘rb’,同时检查图片类型是否与你自己的数据集的格式一致。还有第67行,可以修改几张图片转为一个tfrecords,我的数据集比较大,选择了200张转为一个,这个具体视自己的数据集而定。
 # Read the image file.
   filename = directory + DIRECTORY_IMAGES + name + '.jpg'
   image_data = tf.gfile.FastGFile(filename, 'rb').read()
# TFRecords convertion parameters.
RANDOM_SEED = 4242
SAMPLES_PER_FILES = 200
  1. 接下来就可以进行数据转换了。在SSD_test_VL45文件夹下新建tf_convert_data.sh文件。复制如下第一段代码,运行tf_convert_data.sh文件,完成训练数据的转换。修改代码成第二段,再运行tf_convert_data.sh文件,完成测试数据的转换。其中具体的路径和文件夹的名称根据自己的来。转换完成后将会在前文提到的两个tfrecords文件夹中看到相应的文件。
python  tf_convert_data.py \
    --dataset_name=pascalvoc \
    --dataset_dir=./data/VL45-train/ \
    --output_name=voc_2007_train \
    --output_dir=./data/VL45-train/tfrecords
python  tf_convert_data.py \
    --dataset_name=pascalvoc \
    --dataset_dir=./data/VL45-test/ \
    --output_name=voc_2007_test \
    --output_dir=./data/VL45-test/tfrecords

3.配置300x300的网络

接下来就到了配置网络部分了,首先要对一些文件进行修改。

  1. train_ssd_network.py文件中修改:
    (1)多少次显示一下结果(100),多少次保存一下模型(1000)。
    (2)开始学习率(0.001),最终学习率(0.000001)。
    (3)训练类别(45+1)
    (4)batch size大小(4)
    (5)最大训练步骤(800000)
    还有其他的参数也可以进行更改。
   tf.app.flags.DEFINE_integer(
       'log_every_n_steps', 100,
	   'The frequency with which logs are print.')
   tf.app.flags.DEFINE_integer(
	   'save_summaries_secs', 1000,  
       'The frequency with which summaries are saved, in seconds.')
   tf.app.flags.DEFINE_integer(
	   'save_interval_secs', 1000,  
	   'The frequency with which the model is saved, in seconds.')
   tf.app.flags.DEFINE_float('learning_rate', 0.001, 'Initial learning rate.')
   tf.app.flags.DEFINE_float(
   		'end_learning_rate', 0.000001,
   		'The minimal end learning rate used by a polynomial decay learning rate.')
   tf.app.flags.DEFINE_integer(
   		'num_classes', 46, 'Number of classes to use in the dataset.')
   tf.app.flags.DEFINE_integer(
   		'batch_size', 4, 'The number of samples in each batch.')
   tf.app.flags.DEFINE_integer('max_number_of_steps', 800000, 
                        	   'The maximum number of training steps.')
  1. eval_ssd_network.py修改:
    (1)类别
    (2)batch size 大小
   tf.app.flags.DEFINE_integer(
 	  'num_classes', 46, 'Number of classes to use in the dataset.')
   tf.app.flags.DEFINE_integer(
 	  'batch_size', 4, 'The number of samples in each batch.')
  1. nets/ssd_vgg_300.py文件修改类别:
 	num_classes=46,
    no_annotation_label=46,
  1. datasets/pascalvoc_2007.py文件修改:
    类别后面的数字是该类别包含的图片数量和出现的次数,这个数字没有实际作用,不影响训练,所以如果你进行统计了可以如实填写,我没有统计所以统一写了1。
    SPLITS_TO_SIZES是训练集(35010)和测试集(9990)包含的图片数量,还有NUM_CLASSES(45)是类别数量也要如实填写。
TRAIN_STATISTICS = {
    'none': (0, 0),
    'BAIC GROUP': (1, 1),
    'Ford': (1, 1),
    'SKODA': (1, 1),
    'Venucia': (1, 1),
    'HONDA': (1, 1),
    'NISSAN': (1, 1),
    'Cadillac': (1, 1),
    'SUZUKI': (1, 1),
    'GEELY': (1, 1),
    'Porsche': (1, 1),
    'Jeep': (1, 1),
    'BAOJUN': (1, 1),
    'ROEWE': (1, 1),
    'LINCOLN': (1, 1),
    'TOYOTA': (1, 1),
    'Buick': (1, 1),
    'Chery': (1, 1),
    'KIA': (1, 1),
    'HAVAL': (1, 1),
    'Audi': (1, 1),
    'LAND ROVER': (1, 1),
    'Volkswagen': (1, 1),
    'Trumpchi': (1, 1),
    'CHANGAN': (1, 1),
    'Morris Garages': (1, 1),
    'Renault': (1, 1),
    'LEXUS': (1, 1),
    'BMW': (1, 1),
    'MAZDA': (1, 1),
    'Mercedes-Benz': (1, 1),
    'HYUNDAI': (1, 1),
    'Chevrolet': (1, 1),
    'BYD': (1, 1),
    'PEUGEOT': (1, 1),
    'Citroen': (1, 1),
    'Huachen Auto Group': (1, 1),
    'Volvo': (1, 1),
    'Mitsubishi': (1, 1),
    'Subaru': (1, 1),
    'GMC': (1, 1),
    'Infiniti': (1, 1),
    'FAW Haima': (1, 1),
    'SGMW': (1, 1),
    'Soueast Motor': (1, 1),
    'QOROS': (1, 1),
    'total': (35010, 35010),
}
TEST_STATISTICS = {
    'none': (0, 0),
    'BAIC GROUP': (1, 1),
    'Ford': (1, 1),
    'SKODA': (1, 1),
    'Venucia': (1, 1),
    'HONDA': (1, 1),
    'NISSAN': (1, 1),
    'Cadillac': (1, 1),
    'SUZUKI': (1, 1),
    'GEELY': (1, 1),
    'Porsche': (1, 1),
    'Jeep': (1, 1),
    'BAOJUN': (1, 1),
    'ROEWE': (1, 1),
    'LINCOLN': (1, 1),
    'TOYOTA': (1, 1),
    'Buick': (1, 1),
    'Chery': (1, 1),
    'KIA': (1, 1),
    'HAVAL': (1, 1),
    'Audi': (1, 1),
    'LAND ROVER': (1, 1),
    'Volkswagen': (1, 1),
    'Trumpchi': (1, 1),
    'CHANGAN': (1, 1),
    'Morris Garages': (1, 1),
    'Renault': (1, 1),
    'LEXUS': (1, 1),
    'BMW': (1, 1),
    'MAZDA': (1, 1),
    'Mercedes-Benz': (1, 1),
    'HYUNDAI': (1, 1),
    'Chevrolet': (1, 1),
    'BYD': (1, 1),
    'PEUGEOT': (1, 1),
    'Citroen': (1, 1),
    'Huachen Auto Group': (1, 1),
    'Volvo': (1, 1),
    'Mitsubishi': (1, 1),
    'Subaru': (1, 1),
    'GMC': (1, 1),
    'Infiniti': (1, 1),
    'FAW Haima': (1, 1),
    'SGMW': (1, 1),
    'Soueast Motor': (1, 1),
    'QOROS': (1, 1),
    'total': (9990, 9990),
}
SPLITS_TO_SIZES = {
    'train': 35010,
    'test': 9990,
}
SPLITS_TO_STATISTICS = {
    'train': TRAIN_STATISTICS,
    'test': TEST_STATISTICS,
}
NUM_CLASSES = 45

4.训练300x300的网络

以上就完成了训练前的配置工作,接下来就可以进行训练了。

  1. 在SSD_test_VL54文件夹下新建train_model_300文件夹留作存放训练模型。
  2. 在SSD_test_VL54文件夹下新建train_VOC2007_300.sh文件,复制以下代码:
    对应参数和路径有不同的自行修改,其他博客会有加载VGG16的部分模型参数的代码,但是我训练以后发现效果特别差,所以这里就没有加载参数,而是直接进行训练。
DATASET_DIR=./data/tfrecordsdata/
TRAIN_DIR=./train_model/
CHECKPOINT_PATH=./checkpoints/vgg_16.ckpt

python train_ssd_network.py \
    --train_dir=./train_model_300/ \
    --dataset_dir=./data/VL45-train/tfrecords/ \
    --dataset_name=pascalvoc_2007 \
    --dataset_split_name=train \
    --model_name=ssd_300_vgg \
    --save_summaries_secs=100 \
    --save_interval_secs=1000 \
    --weight_decay=0.0005 \
    --optimizer=adam \
    --learning_rate=0.0001 \
    --learning_rate_decay_factor=0.94 \
    --batch_size=4 \
  1. 完成以上操作以后,终端输入 bash train_VOC2007_300.sh 命令即可开始训练。

5.测试300x300的网络

  1. 在SSD_test_VL45文件夹下新建result_300文件夹用以存放测试结果。
  2. 在SSD_test_VL45文件夹下新建一个test_VOC2007.sh文件,复制下列代码,相应路径根据自己的进行修改,然后运行即可得到检测结果。
python eval_ssd_network.py \
       --eval_dir=./result_300/ \
       --dataset_dir=./data/VL45-test/tfrecords/ \
       --dataset_name=pascalvoc_2007 \
       --dataset_split_name=test \
       --model_name=ssd_300_vgg \
       --checkpoint_path=./train_model_300/model.ckpt-800000 \
       --batch_size=1
  1. 原程序中默认的是输出VOC2007和VOC2012的mAP值,只看07的结果就可以了 ,如果想得到每一类的AP值,可以更改 eval_ssd_network.py中的代码,将对应位置的#做添加或去除处理就可以。
               # Average precision VOC07.
               v = tfe.average_precision_voc07(prec, rec)
               summary_name = 'AP_VOC07/%s' % c
               op = tf.summary.scalar(summary_name, v, collections=[])
               op = tf.Print(op, [v], summary_name)
               tf.add_to_collection(tf.GraphKeys.SUMMARIES, op)
               aps_voc07[c] = v

               # Average precision VOC12.
               v = tfe.average_precision_voc12(prec, rec)
               summary_name = 'AP_VOC12/%s' % c
               op = tf.summary.scalar(summary_name, v, collections=[])
               # op = tf.Print(op, [v], summary_name)
               tf.add_to_collection(tf.GraphKeys.SUMMARIES, op)
               aps_voc12[c] = v

           # Mean average precision VOC07.
           summary_name = 'AP_VOC07/mAP'
           mAP = tf.add_n(list(aps_voc07.values())) / len(aps_voc07)
           op = tf.summary.scalar(summary_name, mAP, collections=[])
           op = tf.Print(op, [mAP], summary_name)
           tf.add_to_collection(tf.GraphKeys.SUMMARIES, op)

           # Mean average precision VOC12.
           summary_name = 'AP_VOC12/mAP'
           mAP = tf.add_n(list(aps_voc12.values())) / len(aps_voc12)
           op = tf.summary.scalar(summary_name, mAP, collections=[])
           # op = tf.Print(op, [mAP], summary_name)
           tf.add_to_collection(tf.GraphKeys.SUMMARIES, op)

6.配置512x512的模型

  1. 修改nets/ssd_vgg_512.py的类别:
  	num_classes=46,
    no_annotation_label=46,
  1. 修改nets/np_methods.py文件中的尺寸和类别(注意有两处):
    img_shape=(512, 512),
    num_classes=46,
  1. 修改preprocessing/ssd_vgg_preprocessing.py,文件中300改成512:
	EVAL_SIZE = (512, 512)
  1. 修改train_ssd_network.py文件,
tf.app.flags.DEFINE_string(
    'model_name', 'ssd_512_vgg', 'The name of the architecture to train.')

7.在300x300的基础上训练512x512的模型

  1. 在SSD_test_VL54文件夹下新建train_model_512文件夹留作存放训练模型。
  2. 在SSD_test_VL54文件夹下新建train_VOC2007_512.sh文件,复制以下代码:
python train_ssd_network.py \
    --train_dir=./train_model_512/ \
    --dataset_dir=./data/VL45-train/tfrecords/ \
    --dataset_name=pascalvoc_2007 \
    --dataset_split_name=train \
    --model_name=ssd_512_vgg \
    --checkpoint_path=./train_model_300/model.ckpt-800000 \
    --checkpoint_model_scope=ssd_300_vgg \
    --checkpoint_exclude_scopes=ssd_512_vgg/block7,ssd_512_vgg/block7_box,ssd_512_vgg/block8,ssd_512_vgg/block8_box,ssd_512_vgg/block9,ssd_512_vgg/block9_box,ssd_512_vgg/block10,ssd_512_vgg/block10_box,ssd_512_vgg/block11,ssd_512_vgg/block11_box,ssd_512_vgg/block12,ssd_512_vgg/block12_box \
    --save_summaries_secs=100 \
    --save_interval_secs=1000 \
    --weight_decay=0.0005 \
    --optimizer=adam \
    --learning_rate=0.001 \
    --learning_rate_decay_factor=0.94 \
    --batch_size=4 \
  1. 运行train_VOC2007_512.sh文件即可进行训练。

8.测试512x512的网络

  1. 在SSD_test_VL45文件夹下新建result_512文件夹用以存放测试结果。
  2. 修改test_VOC2007.sh文件:
python eval_ssd_network.py \
       --eval_dir=./result_512/ \
       --dataset_dir=./data/VL45-test/tfrecords/ \
       --dataset_name=pascalvoc_2007 \
       --dataset_split_name=test \
       --model_name=ssd_512_vgg \
       --checkpoint_path=./train_model_512/model.ckpt-800000 \
       --batch_size=1
  1. 运行test_VOC2007.sh文件即可进行测试。

9.查看检测结果

我的数据集用512的网络得到的mAP更好一些,所以我就使用训练好的512的模型来测试一下检测效果。

  1. 更改notebooks/ssd_notebook.ipynb文件,300均改成512,如果你要测试300的模型就不用改。
  2. 在SSD_test_VL45文件夹下新建test.py文件,复制notebooks/ssd_notebook.ipynb中的代码过去。修改模型路径和测试文件夹。
	# Restore SSD model.
	ckpt_filename = '/home/clj/SSD_test_VL45/train_model_512/model.ckpt-800000'
	# Test on some demo image and visualize output.
	path = '/home/clj/SSD_test_VL45/data/VL45-test/JPEGImages/'
	image_names = sorted(os.listdir(path))
  1. i代表第几张图片,i=-1时表示最后一张
	img = mpimg.imread(path + image_names[i])
  1. 我的linux系统没有图形界面,所以只能把测试结果保存为图片再下载到本地进行查看,而且为了一次测试多张,我使用了一个for循环。在SSD_test_VL45文件夹下新建了一个output文件夹留作存放测试结果图片。最终这一部分的具体代码改动如下:
	# Test on some demo image and visualize output.
	path = '/home/clj/SSD_test_VL45/data/VL45-test/JPEGImages/'
	image_names = sorted(os.listdir(path))
	#print(image_names)
	for i in range(1,6):
       	 img = mpimg.imread(path + image_names[i])
	#print(img)
         rclasses, rscores, rbboxes = process_image(img)

	# visualization.bboxes_draw_on_img(img, rclasses, rscores, rbboxes, visualization.colors_plasma)
 	     visualization.plt_bboxes(img, rclasses, rscores, rbboxes)
  	     plt.savefig("output/"+image_names[i])
  1. 最终的测试结果图如下:

10.总结

训练和测试的过程大体就是这些,还有一些细节可能还没有想到,以后还会有补充。
当然训练过程中还遇到了很多的问题,一时也不好整理,不过也都解决了,所以有问题的可以下方留言一起探讨。

最后,以上的步骤也都参考了一些大神的博客,感谢各位大神。
1.https://blog.csdn.net/Angela_qin/article/details/80930267
2.https://blog.csdn.net/duanyajun987/article/details/81564081
3.https://blog.csdn.net/qq_36396104/article/details/84639904
4.https://blog.csdn.net/liuyan20062010/article/details/78905517

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值