环境列表如下:Win10系统,tensorflow版本为1.13,python版本3.6,模型框架SSD。目标检测模型训练过程具体步骤如下:
1,制作Pascal VOC图片数据集:
2,配置SSD:
(1)首先,下载SSD代码
由于本案例是基于tensorflow的,因此,在github上下载一个基于tensorflow的SSD
(2)转换文件格式
将voc_2007格式的文件转换为tfrecord格式,tfrecord数据文件为tensorflow中的一种将图像数据和标签统一存储的二进制文件,能更加快速地在tensorflow中复制、移动、读取和存储等。在window下打开终端并在SSD-Tensorflow-master的目录下执行以下命令。SSD-Tensorflow-master提供了转换格式的脚本,转换命令如下,注意此处转换格式时使用的tensorflow版本最好为tf1版本:
python tf_convert_data.py --dataset_name=pascalvoc --dataset_dir=C:\Users\username\Desktop\ImageData\Pascal_VOC\ --output_name=voc_2007_train --output_dir=C:\Users\username\Desktop\mobilnetv3_ssd\SSD-Tensorflow-Test\test_cat_tfrecord\
其中:
dataset_dir=C:\Users\username\Desktop\ImageData\Pascal_VOC\ #此处改为VOC数据集制做的文件夹
output_dir=C:\Users\username\Desktop\mobilnetv3_ssd\SSD-Tensorflow-Test\test_cat_tfrecord\ #将在执行处新建一个文件夹test_cat_tfrecord,这里我在SSD-Tensorflow-master文件夹下执行,因此将在此文件夹下新建一个名为test_cat_tfrecord的文件夹保存.tfrecord格式数据
在转换过程中运行时还遭遇了以下错误:
错误1:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte
解决办法:在pascalvoc_to_tfrecords.py程序中将下面语句中
image_data = tf.gfile.FastGFile(filename, 'r').read()
改成:
image_data = tf.gfile.FastGFile(filename, 'rb').read()
错误2:
KeyError: 'jumao'
解决办法:由于是我们自定义的物体,因此,要修改SSD-Tensorflow-master中关于物体类别的定义,打开SSD-Tensorflow-master/datasets/pascalvoc_common.py文件,进行修改,将VOC_LABELS中的其它无关类别全部删掉,增加jumao,lanmao,buoumoa的名称、ID、类别,如下:
VOC_LABELS = {
'none': (0, 'Background'),
'jumao': (1, 'Animal'),
'lanmao': (2, 'Animal'),
'buoumao': (3, 'Animal'),
}
最终,在执行了python命令后,在test_cat_tfrecord文件夹下生成了如下.record文件,这里只生成了一个文件可能是因为本人仅为了测试程序用,标注的图片样本数较少,因此生成的.record文件不多,控制生成tfrecord文件多少的代码在pascalvoc_to_tfrecords.py文件下,其中SAMPLES_PER_FILES = 200控制200张图片生成一个tfrecords。
之后再修改datasets/pascalvoc_2007.py,其中标签改为自己标注的图像:
同时,其中,根据自己训练数据修改:NUM_CLASSES = 类别数,这里我设置为8。
打开nets/ssd_vgg_300.py 修改类别个数,根据自己训练类别数修改96 和97行:等于类别数+1;如下图:
打开主目录下的eval_ssd_network.py修改类别个数,修改66行的类别个数:等于类别数+1;
3,下载预训练模型:
SSD-Tensorflow提供了预训练好的模型,这里我们利用vgg16模型进行训练
以下是一些谷歌云上提供的预训练权重,这里本人未成功下载,就不作过多介绍。
解压并使用vgg_16_2016_08_28.tar.gz的权重。解压后新建一个文件夹保存,内容如下:
4,利用预训练模型开始训练模型:
在训练模型之前,有个参数要修改下,打开SSD-Tensorflow-master/train_ssd_network.py找到里面的DATA_FORMAT参数项,如果是使用cpu训练则值为NHWC,如果是使用gpu训练则值为NCHW,默认为GPU训练,如下:
DATA_FORMAT = 'NCHW' # gpu
在tensorflow1.13环境切换到SSD-Tensorflow-master目录下下执行以下命令:
python train_ssd_network.py --train_dir=C:\Users\username\Desktop\mobilnetv3_ssd\SSD-Tensorflow-Test\cat_models --dataset_dir=C:\Users\username\Desktop\mobilnetv3_ssd\SSD-Tensorflow-Test\test_cat_tfrecord --dataset_name=pascalvoc_2007 --dataset_split_name=train --model_name=ssd_300_vgg --checkpoint_path=C:\Users\username\Desktop\mobilnetv3_ssd\VGG_VOC0712_SSD_300x300_ft_iter_120000\vgg_16.ckpt --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.0001 --batch_size=1 --gpu_memory_fraction=0.9
各个参数意义如下:
train_dir为训练生成模型的存放路径,这里我在SSD-Tensorflow-master目录下新建一个cat_models文件夹用于保存。
dataset_dir为数据存放路径,即之前转换后的tfrecord文件的存放路径。
dataset_name为数据名的前缀,一般不用更改,使用的是VOC2012格式的改为pascalvoc_2012即可。
dataset_split_name需要与之前生成tfrecord文件的文件名中第三个单词保持一致,训练下定义为train即可。
model_name为加载的模型的名字,这里为ssd_300_vgg。
checkpoint_path为所加载预训练模型的路径,这里为,刚刚解压下来的预训练模型的文件路径。
checkpoint_model_scope为所加载模型里面的作用域名
checkpoint_exclude_scopes指定哪些层的参数不需要从vgg16模型里面加载进来
trainable_scopes指定哪些层的参数是需要训练的,未指定的参数保持不变,若注释掉此命令,所有的参数均需要训练
save_summaries_secs为每多少秒保存一下日志,这里我设置为60s。
save_interval_secs为每多少秒保存一下模型,这里我设置为600s。
weight_decay为正则化的权值衰减的系数。
optimizer为选取的最优化函数。
learning_rate为学习率。
batch_size为表示批量处理的数量,显存越大则可以设置越大。小显存设置为1即可。
gpu_memory_fraction指定占用gpu内存的百分比
执行命令后碰到如下错误:
错误1:
2022-04-10 19:47:17.769976: E tensorflow/stream_executor/cuda/cuda_driver.cc:806] failed to allocate 3.60G (3865470464 bytes) from device: CUDA_ERROR_OUT_OF_MEMORY: out of memory
2022-04-10 19:47:17.770090: E tensorflow/stream_executor/cuda/cuda_driver.cc:806] failed to allocate 3.24G (3478923264 bytes) from device: CUDA_ERROR_OUT_OF_MEMORY: out of memory
解决办法:是GPU内存不足造成的。需要在运行的train_ssd_network.py程序前加以下一段代码:
from tensorflow import ConfigProto
from tensorflow import InteractiveSession
config = ConfigProto()
config.gpu_options.allow_growth = True
session = InteractiveSession(config=config)
此时成功训练过程运行截图:
等待loss稳定在一个比较小的值之间,则可以停止训练。(直接关闭窗口以上即可)
5,监控训练过程:
进入 tensorflow环境下进入C:\Users\username\Desktop\mobilnetv3_ssd\SSD-Tensorflow-Test目录,在终端下输入以下指令:
tensorboard --logdir="cat_models"
并在浏览器中输入127.0.0.1:6006即可查看训练过程
错误问题记录,在训练完毕之后再重新打开tensorboard查看时,出现以下错误:
解决办法:
在tensorboard命令的末尾加一句--host=127.0.0.1,即:
tensorboard --logdir="cat_models" --host=127.0.0.1
再在浏览器下输入网址:127.0.0.1:6006即可打开。
最后,训练完毕的模型将保存在C:\Users\username\Desktop\mobilnetv3_ssd\SSD-Tensorflow-Test\cat_models目录下,如下图所示。
6,训练模型结果测试:
SSD-Tensorflow-master自带了一个notebooks脚本,可通过jupyter直接使用模型。没有安装Jupyter则在tensorflow环境下安装,执行以下命令,若是已经完成安装jupyter的,跳过此步:
conda install jupyter
启动jupyter-notebook,在tensorflow环境下,进入SSD-Tensorflow-master目录,执行以下代码:
cd C:\Users\username\Desktop\mobilnetv3_ssd
jupyter-notebook
成功打开jupyter后,进入SSD-Tensorflow-Test\notebooks目录,然后打开ssd_notebook.ipynb并更改以下几处:
a,In[6]代码块中设置训练完毕的模型路径:
# Restore SSD model.
ckpt_filename = 'C:\Users\username\Desktop\mobilnetv3_ssd\SSD-Tensorflow-Test\cat_models\model.ckpt-22105'
b,在最后的代码块中,设置要测试的图像路径path,选取一张图片放在一个新文件夹下即可:
# Test on some demo image and visualize output.
path = 'C:\Users\username\Desktop\ImageData\testImg\000058.jpg'
image_names = sorted(os.listdir(path))
由于只有1张测试的图片,再将图片数目改为1张,代码改为:
img = mpimg.imread(path + image_names[0])
然后点击菜单“Cell”,点击子菜单“Run All”,便能按顺序全部执行代码,并显示出结果出来:
其中,左边字数3含义为之前定义的buoumao定义的序号, 右边0.803表示检测的概率。
在此处中遇到的问题如下:
错误1:
ImportError: cannot import name ‘ssd_vgg_300’
解决办法:为ssd_notebook.ipynb文件存放位置路径问题,将此文件拷贝到SSD-Tensorflow-Test主目录下,再重启jupyter notebook并打开。
错误2:
SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 2-3: truncated \UXXXXXXXX escape
解决办法:在windows系统当中读取文件路径可以使用,但是在python字符串中\有转义的含义,如\t可代表TAB,\n代表换行,所以我们需要采取一些方式使得\不被解读为转义字符。在路径前面加r,即保持字符原始值的意思或者将\全部改为\\
。即更改路径为:
ckpt_filename = r'C:\Users\username\Desktop\mobilnetv3_ssd\SSD-Tensorflow-Test\cat_models\model.ckpt-22105'
path = 'C:\\Users\\username\\Desktop\\ImageData\\testImg\\000058.jpg'
错误3:
NotADirectoryError: [WinError 267] 目录名称无效。:
解决办法:是因为只需要path信息,不要写到文件。将path路径更改为:
path = 'C:\\Users\\username\\Desktop\\ImageData\\testImg\\'