前记: 本篇博客纯属记录我在用VOC数据集以及自己的数据集训练SSD-Tensorflow时遇到的一些问题以及部分问题的解决方法。
- 搭建SSD-Tensorflow框架,star最多的balancap大神的GitHub地址:https://github.com/balancap/SSD-Tensorflow
- 准备数据
(1)VOC数据集:地址http://host.robots.ox.ac.uk/pascal/VOC/ 需翻墙获取
数据集下载后解压得到一个名为VOCdevkit的文件夹,对文件夹里的内容做一个简单的介绍。
- Annotation文件夹存放的是xml文件,是图片的标注信息。
- ImageSets文件夹存放的是txt文件,这些txt将数据集的图片分成了各种集合。如Main下的train.txt中记录的是用于训练的图片集合
- JPEGImages文件夹存放的是数据集的原图片
- SegmentationClass以及SegmentationObject文件夹存放的是分割后的图片
(2) 自己的数据集
按照VOC数据集的格式转化即可,网上有相应的代码实现,注意图片格式要为“.jpg"
- 将图像数据转化为tfrecord格式
创建一个tf_convert_data.sh脚本文件,写入以下代码:
tf_convert_data.sh
DATASET_DIR=./data/VOCtrainval_06-Nov-2007/VOCdevkit/VOC2007/ #此处为你需要转化的训练数据
OUTPUT_DIR=./tfrecords #用于存放输出数据的文件夹,可以自己指定
python tf_convert_data.py \
--dataset_name=pascalvoc \
--dataset_dir=${DATASET_DIR} \
--output_name=voc_2007_train \ #输出tfrecord格式前置名称,如果是测试数据,需改为voc_2007_test
--output_dir=${OUTPUT_DIR}
若是将自己的数据转化为tfrecord格式需要对部分源码进行修改:
在SSD-Tensorflow-master—>datasets—>pascalvoc_common.py下对修改VOC_LABELS为自己的label
"""
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'),
}
"""
比如只检测人,修改为
VOC_LABELS = {
'none': (0, 'Background'),
'person':(1, 'Person')
然后再执行上述脚本命令。
- 训练
训练VOC数据集
创建一个shell文件,命名为train_ssd_network.sh(可随意),写入以下脚本命令
#此训练为基于预训练好的权重参数vgg_16的基础之上进行的训练,其中
# checkpoint_exclude_scopes:指定哪些层不需要从vgg_16.ckpt加载参数,即这些层的参数随机初始化。
# trainable_scopes:指定需要需要训练的层。若注释掉,则表明所有层均需要参与训练。
DATASET_DIR=./tfrecords/ #存放的数据集
TRAIN_DIR=./log/train_logs #用于保存训练过程中的权重参数,图信息等,可通过tensorboard --logdir显示
CHECKPOINT_PATH=./checkpoints/vgg_16.ckpt #预训练好的vgg_16权重参数,也可以指定为预训练好的ssd_300_vgg.ckpt
python train_ssd_network.py \
--train_dir=${TRAIN_DIR} \
--dataset_dir=${DATASET_DIR} \
--dataset_name=pascalvoc_2007 \ #网络里定死的数据格式,最好不要随意修改,要与数据名称一致.
--dataset_split_name=train \
--model_name=ssd_300_vgg \
--checkpoint_path=${CHECKPOINT_PATH} \
--checkpoint_model_scope=vgg_16 \
--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 \
--save_interval_secs=600 \
--weight_decay=0.0005 \
--optimizer=adam \
--learning_rate=0.001 \
--learning_rate_decay_factor=0.94 \
--batch_size=32
需要在train_ssd_network.py修改第154行 设置最大训练步数,将None设置为100000,否则会一直训练下去。
5. 基于自己训练的结果微调
DATASET_DIR=./tfrecords/
TRAIN_DIR=./log/fine_tuning_logs/
CHECKPOINT_PATH=./log/train_logs/model.ckpt-xxxx
python train_ssd_network.py \
--train_dir=${TRAIN_DIR} \
--dataset_dir=${DATASET_DIR} \
--dataset_name=pascalvoc_2012 \
--dataset_split_name=train \
--model_name=ssd_300_vgg \
--checkpoint_path=${CHECKPOINT_PATH} \
--checkpoint_model_scope=ssd_300_vgg \
--save_summaries_secs=60 \
--save_interval_secs=600 \
--weight_decay=0.0005 \
--optimizer=adam \
--learning_rate=0.0001 \
--learning_rate_decay_factor=0.94 \
--batch_size=32
- 对训练结果评估
DATASET_DIR=./tfrecords/ #存放测试数据集的文件夹,提前将测试数据转化为tfrecord格式存放在该目录下(也可以自行指定)
EVAL_DIR=./logs/ #保存评估结果
CHECKPOINT_PATH=./checkpoints/ssd_300_vgg.ckpt #可设置为自己训练的模型参数,即对自己的结果评估
python eval_ssd_network.py \
--eval_dir=${EVAL_DIR} \
--dataset_dir=${DATASET_DIR} \
--dataset_name=pascalvoc_2007 \
--dataset_split_name=test \
--model_name=ssd_300_vgg \
--checkpoint_path=${CHECKPOINT_PATH} \
--batch_size=1
问题汇总:
-
Key vgg_16/block10/conv1x1/biases not found in checkpoint
[[Node: save_1/RestoreV2 = RestoreV2[dtypes=[DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_FLOAT, …, DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_FLOAT], _device="/job:localhost/replica:0/task:0/device:CPU:0"](_arg_save_1/Const_0_0, save_1/RestoreV2/tensor_names, save_1/RestoreV2/shape_and_slices)]]
解决办法:将–checkpoint_model_scope=vgg_16 \更改为–checkpoint_model_scope=ssd_300_vgg \ -
在windows对下载解压好的SSD-Tensorflow-master进行demo测试时,运行ssd_notebook.ipynb发现ssd_300_vgg.ckpt文件始终加载不进去?
解决办法:看ssd_300_vgg.ckpt是否在checkpoints文件夹下,windows解压压缩文件会创建一个ssd_300_vgg的文件夹,此时将ssd_300_vgg.ckpt文件移出到checkpoints目录下即可。linux下解压不存在这个问题。 -
tensorflow.python.framework.errors_impl.InternalError: Failed to create session
解决办法:使用nvidia-smi查看是否GPU全部被占用,若存在空闲GPU,指定GPU运行程序 -
InvalidArgumentError: Assign requires shapes of both tensors to match. lhs shape= [8] rhs shape= [84]
[[Node: save_1/Assign_4 = Assign[T=DT_FLOAT, _class=[“loc:@ssd_300_vgg/block10_box/conv_cls/biases”], use_locking=true, validate_shape=true, _device="/job:localhost/replica:0/task:0/device:CPU:0"](ssd_300_vgg/block10_box/conv_cls/biases, save_1/RestoreV2_4)]]
解决办法:注销掉checkpoint_model_scope=ssd_300_vgg这一行 -
训练过程中loss为nan
解决办法:调小学习率,调小batchsize -
All bounding box coordinates must be in [0.0, 1.0]
解决办法:产生原因是图片的标注信息超过了图片尺寸。将pascalvoc_to_tfrecords.py第116行代码修改如下:
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),
))
参考链接
https://github.com/balancap/SSD-Tensorflow
https://blog.csdn.net/liuyan20062010/article/details/78905517#commentBox
https://blog.csdn.net/w5688414/article/details/78395177
https://my.oschina.net/u/876354/blog/1927351