一、首先下载代码:https://github.com/balancap/SSD-Tensorflow 目前是github基于TensorFlow星星最高的开源SSD。
2、解压至某个文件夹,我这里解压的路径是 /media/comway/data/dial_SSD/SSD-Tensorflow-master
若是其他路径,后面进行相应的更改。
3、制作2007VOC数据集(谷歌一下,一大堆资料),通过labelImg制作每张图片的标签。然后制作2007VOC数据集。如下图所示。简单解释下:Annotations文件夹下有保存每张图片的xml文件。ImageSets有四个xml文件,用来划分训练验证测试集。JPEGImages文件夹下保存的是图片数据。
附分割训练测试验证集的代码:
import os
import random
xmlfilepath=r'/media/comway/data/DialVOC/Annotations'
saveBasePath=r"/media/comway/data/DialVOC"
trainval_percent=0.9
train_percent=0.9
total_xml = os.listdir(xmlfilepath)
num=len(total_xml)
list=range(num)
tv=int(num*trainval_percent)
tr=int(tv*train_percent)
trainval= random.sample(list,tv)
train=random.sample(trainval,tr)
print("train and val size",tv)
print("traub suze",tr)
ftrainval = open(os.path.join(saveBasePath,'ImageSets/Main/trainval.txt'), 'w')
ftest = open(os.path.join(saveBasePath,'ImageSets/Main/test.txt'), 'w')
ftrain = open(os.path.join(saveBasePath,'ImageSets/Main/train.txt'), 'w')
fval = open(os.path.join(saveBasePath,'ImageSets/Main/val.txt'), 'w')
for i in list:
name=total_xml[i][:-4]+'\n'
if i in trainval:
ftrainval.write(name)
if i in train:
ftrain.write(name)
else:
fval.write(name)
else:
ftest.write(name)
ftrainval.close()
ftrain.close()
fval.close()
ftest .close()
附将数据重命名为六位数据代码:
# -*- coding:utf8 -*-
import os
class BatchRename():
'''
批量重命名文件夹中的图片文件
'''
def __init__(self):
#我的图片文件夹路径horse
self.path = '/media/comway/data/dialData'
def rename(self):
filelist = os.listdir(self.path)
total_num = len(filelist)
i = 1
n = 6
for item in filelist:
if item.endswith('.jpg'):
n = 6 - len(str(i))
src = os.path.join(os.path.abspath(self.path), item)
dst = os.path.join(os.path.abspath(self.path), str(0)*n + str(i) + '.jpg')
try:
os.rename(src, dst)
print 'converting %s to %s ...' % (src, dst)
i = i + 1
except:
continue
print 'total %d to rename & converted %d jpgs' % (total_num, i)
if __name__ == '__main__':
demo = BatchRename()
demo.rename()
4、 将VOC2007数据转换文件格式,变成TensorFlow可接受的数据格式tfrecord。
a、首先,打开进入SSD-Tensorflow-master—>datasets—>pascalvoc_common.py 更改代码,根据自己情况更改,有几类就改成几类。
VOC_LABELS = {
'none': (0, 'Background'),
'aeroplane': (1, 'Vehicle'),
'bicycle': (2, 'Vehicle'),
'bird': (3, 'Animal'),
'boat': (4, 'Vehicle'),
'bottle': (5, 'Indoor'),
'bus': (6, 'Vehicle'),
'car': (7, 'Vehicle'),
'cat': (8, 'Animal'),
'chair': (9, 'Indoor'),
'cow': (10, 'Animal'),
'diningtable': (11, 'Indoor'),
'dog': (12, 'Animal'),
'horse': (13, 'Animal'),
'motorbike': (14, 'Vehicle'),
'Person': (15, 'Person'),
'pottedplant': (16, 'Indoor'),
'sheep': (17, 'Animal'),
'sofa': (18, 'Indoor'),
'train': (19, 'Vehicle'),
'tvmonitor': (20, 'Indoor'),
}
b、SSD-Tensorflow-master—>datasets—>pascalvoc_to_tfrecords.py 然后更改文件的83行读取方式为’rb’)
如下图所示,SAMPLES_PER_FILES的竖直,意思是200张图片转换为一个tfrecord文件。
c 、在SSD-Tensorflow-master文件夹下创建converttfrecord.sh文件,将下列代码写进去。
python tf_convert_data.py \
--dataset_name=pascalvoc \ #不可更改
--dataset_dir=/media/comway/data/dial_SSD/DialVOC/ \ #你的制作的VOC数据集。
--output_name=voc_2007_train \ #输出的record文件前缀
--output_dir=/media/comway/data/dial_SSD/SSD-Tensorflow-master/dialvoc-train-tfrecords #输出tfreord的路径。
5、训练模型前,更改文件中数据
train_ssd_network.py修改第154行的最大训练步数,将None改为比如50000。(tf.contrib.slim.learning.training函数中max-step为None时训练会无限进行。)
需要修改的地方:
a. train_ssd_network.py,135行,这里本来是21,我这里改成了2。可以根据自己的类别数更改,数字为类别数加1。
b. nets/ssd_vgg_300.py,我们分析train_ssd_network.py文件就知道,其中引入了from nets import nets_factory模块,在看nets_factory文件,就可以知道引入了ssd_vgg_300。如下图所示,所以我们要对ssd_vgg_300更改。
需要更改的部分如下,在文件96,97行进行更改,将num_classes,no_annotation_label,更改为你的类别数加1,我这里只有一类,所以是2:
c. datasets/pascalvoc_2007.py ,我们分析train_ssd_network.py文件就知道,其中引入了from datasets import dataset_factory模块,再看dataset_factory文件,如下图就可以知道引入了pascalvoc_2007。如下图所示,所以我们要对pascalvoc_2007更改。记住,必须在训练之前改,否则就会出错。
需要更改的部分:
TRAIN_STATISTICS = {
'none': (0, 0),
'aeroplane': (238, 306),
'bicycle': (243, 353),
'bird': (330, 486),
'boat': (181, 290),
'bottle': (244, 505),
'bus': (186, 229),
'car': (713, 1250),
'cat': (337, 376),
'chair': (445, 798),
'cow': (141, 259),
'diningtable': (200, 215),
'dog': (421, 510),
'horse': (287, 362),
'motorbike': (245, 339),
'person': (2008, 4690),
'pottedplant': (245, 514),
'sheep': (96, 257),
'sofa': (229, 248),
'train': (261, 297),
'tvmonitor': (256, 324),
'total': (5011, 12608),
}
TEST_STATISTICS = {
'none': (0, 0),
'aeroplane': (1, 1),
'bicycle': (1, 1),
'bird': (1, 1),
'boat': (1, 1),
'bottle': (1, 1),
'bus': (1, 1),
'car': (1, 1),
'cat': (1, 1),
'chair': (1, 1),
'cow': (1, 1),
'diningtable': (1, 1),
'dog': (1, 1),
'horse': (1, 1),
'motorbike': (1, 1),
'person': (1, 1),
'pottedplant': (1, 1),
'sheep': (1, 1),
'sofa': (1, 1),
'train': (1, 1),
'tvmonitor': (1, 1),
'total': (20, 20),
}
#以上两部分,我没改好像也没错,我查了下好像没用到这个dict。不过也可以改。
SPLITS_TO_SIZES = {
'train': 2229, #这个地方要改成你的训练数据量
'test': 276, #这个地方改成测试数据量
}
SPLITS_TO_STATISTICS = {
'train': TRAIN_STATISTICS,
'test': TEST_STATISTICS,
}
NUM_CLASSES = 1 #记住,这个地方一定要改,否则就会出现shape不匹配等问题。本身应该是20,我这里改成了1.因为我的类别数是1.
d eval_ssd_network.py 修改类别,72行,把um_classes改成你的类别数加1.
这四部分已经改完,接下来就可以进行训练了。
6、训练模型
这里很容易出现问题,请记住,两种情况训练,第一种情况,不加载模型,直接全部训练。第二种情况,加载预训练模型,训练部分参数。
这里比较容易犯错就是,加载训练模型,又全部训练所有参数。如下所示进行训练:
python3 train_ssd_network.py \
--train_dir=/media/comway/data/dial_SSD/SSD-Tensorflow-master/train_log/ \
--dataset_dir=/media/comway/data/dial_SSD/SSD-Tensorflow-master/dialvoc-train-tfrecords \
--dataset_name=pascalvoc_2007 \
--dataset_split_name=train \
--model_name=ssd_300_vgg \
--checkpoint_path=/media/comway/data/dial_SSD/SSD-Tensorflow-master/checkpoints/ssd_300_vgg.ckpt \
--save_summaries_secs=60 \
--save_summaries_secs=600 \
--save_interval_secs=600 \
--weight_decay=0.0005 \
--optimizer=adam \
--learning_rate=0.001 \
--learning_rate_decay_factor=0.94 \
--batch_size=16 \
--gpu_memory_fraction=0.9
如果你的sh脚本文件按这样训练就会出现如下类似错误:
InvalidArgumentError (see above for traceback): Assign requires shapes of both tensors to match. lhs shape= [12] rhs shape= [126]
[[Node: save_1/Assign_29 = Assign[T=DT_FLOAT, _class=["loc:@ssd_300_vgg/block8_box/conv_cls/biases"], use_locking=true, validate_shape=true, _device="/job:localhost/replica:0/task:0/cpu:0"](s
sd_300_vgg/block8_box/conv_cls/biases, save_1/RestoreV2_29)]]
所以只能按我说的两种情况进行训练:
第一种: 不加载模型,直接全部训练
python3 train_ssd_network.py \
--train_dir=/media/comway/data/dial_SSD/SSD-Tensorflow-master/train_log/ \
--dataset_dir=/media/comway/data/dial_SSD/SSD-Tensorflow-master/dialvoc-train-tfrecords \
--dataset_name=pascalvoc_2007 \
--dataset_split_name=train \
--model_name=ssd_300_vgg \
--save_summaries_secs=60 \
--save_interval_secs=600 \
--weight_decay=0.0005 \
--optimizer=adam \
--learning_rate=0.001 \
--learning_rate_decay_factor=0.94 \
--batch_size=16
第二种: 加载预训练模型,训练部分参数。从vgg开始训练其中某些层的参数。其实就是加了--checkpoint_exclude_scopes,与--trainable_scopes。
# 通过checkpoint_exclude_scopes指定哪些层的参数不需要从预训练模型模型里面加载进来
# 通过trainable_scopes指定哪些层的参数是需要训练的,未指定的参数保持不变,若注释掉此命令,所有的参数均需要训练
python3 train_ssd_network.py \
--train_dir=/media/comway/data/dial_SSD/SSD-Tensorflow-master/train_log/ \ #训练生成模型的存放路径
--dataset_dir=/media/comway/data/dial_SSD/SSD-Tensorflow-master/dialvoc-train-tfrecords \ #数据存放路径
--dataset_name=pascalvoc_2007 \ #数据名的前缀,我觉得应该通过这个调用是2007还是2012
--dataset_split_name=train \ #是加载训练集还是测试集
--model_name=ssd_300_vgg \ #加载的模型的名字
--checkpoint_path=/media/comway/data/dial_SSD/SSD-Tensorflow-master/checkpoints/ssd_300_vgg.ckpt \ #所加载模型的路径
--checkpoint_exclude_scopes=ssd_300_vgg/conv6,ssd_300_vgg/conv7,ssd_300_vgg/block8,ssd_300_vgg/block9,ssd_300_vgg/block10,ssd_300_vgg/block11,ssd_300_vgg/block4_box,ssd_300_vgg/block7_box,ssd_300_vgg/block8_box,ssd_300_vgg/block9_box,ssd_300_vgg/block10_box,ssd_300_vgg/block11_box \
--trainable_scopes=ssd_300_vgg/conv6,ssd_300_vgg/conv7,ssd_300_vgg/block8,ssd_300_vgg/block9,ssd_300_vgg/block10,ssd_300_vgg/block11,ssd_300_vgg/block4_box,ssd_300_vgg/block7_box,ssd_300_vgg/block8_box,ssd_300_vgg/block9_box,ssd_300_vgg/block10_box,ssd_300_vgg/block11_box \
--save_summaries_secs=60 \#每60s保存一下日志
--save_interval_secs=600 \ #每600s保存一下模型
--weight_decay=0.0005 \ #正则化的权值衰减的系数
--optimizer=adam \ #选取的最优化函数
--learning_rate=0.001 \ #学习率
--learning_rate_decay_factor=0.94 \ #学习率的衰减因子
--batch_size=16 \
--gpu_memory_fraction=0.9 #指定占用gpu内存的百分比
终结!!!!!!!
参考资料:
https://blog.csdn.net/comway_Li/article/details/85240291
https://www.cnblogs.com/pprp/p/9552402.html#%E9%AA%8C%E8%AF%81
https://github.com/balancap/SSD-Tensorflow