本文主要内容是在应用github上的tensorflow实现的目标检测神经网络ssd的过程以及中间遇到的问题以及解决方法汇总。
github的链接为https://github.com/balancap/SSD-Tensorflow
1、首先是调用模型文件的过程,在./checkpoint/文件夹下,解压ssd_300_vgg.ckpt.zip这个压缩包,然后只需要修改./notebook下的ssd_notebook.ipynb中的文件,主要是将多个部分代码合并在一起,然后修改一下文件的路径,其中import的visualization主要是画图,也就是将预测的方框画在图中,不需要的话可以将相关的代码注释掉。需要注意的是
sys.path.append('../')
这行代码主要是添加python搜索模块的路径,也就是当import一个模块时,默认情况下python解析器会搜索当前目录、已安装的内置模块和第三方模块,通过sys.path可以查看这些路径,sys.path是一个list,所以sys.path.append不是对所有的路径都加了一个前缀,只是在找不到的时候会在这个路径下取找。
然后就是训练(train)和评测(evaluate)的过程了
2、首先是数据集的转化,使用的是VOC2007和VOC2012的数据集,需要将这些数据集转换成tfrecords格式的文件,将数据集解压之后在里面的一层文件夹下有四个文件夹,这就是要传入的DATASET_PATH,但是在转换过程中可能会遇到报错
with tf.python_io.TFRecordWriter(tf_filename) as tfrecord_writer:
NotFoundError
需要修改./datasets下的文件pascalvoc_to_tfrecords.py 209行的代码
with tf.python_io.TFRecordWriter(tf_filename) as tfrecord_writer:
j = 0
为二进制读取
with open(tf_filename, "wb"):
writer = tf.python_io.TFRecordWriter(tf_filename)
j = 0
然后就是报错
utf-8' codec can't decode byte 0xff in position 0: invalid start byte
通过将83行的
image_data = tf.gfile.FastGFile(filename, 'r').read()
其中的读取方式"r"修改为byte方式读取,也就是"rb"来解决报错
3、然后就是训练过程了,训练时可以主要是要将DATASET_DIR设置为用训练数据生成的tfrecords的文件夹,我在训练过程中前面几十个epoch的loss都在15到30之间浮动,查了一下大概在几千epoch之后会稳定在10以下?没时间训练那么久了。
4、最后是evaluate的过程了,仍然是设置参数,可能会遇到报错
TypeError: Can not convert a tuple into a Tensor or Operation ,这个问题主要参见博客SSD输出mAP时出现TypeError: Can not convert a tuple into a Tensor or Operation
但是我在用cpu版本的tensorflow进行evaluate时,出现了一个错误:TypeError: _variable_v2_call() got an unexpected keyword argument 'collections'。通过将./tf_extended/metrics.py第51行的return variables.Variable改为return variables.VariableV1解决,如果还不能解决,尝试把tensorflow的版本调低一点。
还有一个问题我至今没有解决,在设置CHECKPOINT_PATH时,若我设置为一开始unzip的ssd_300_vgg.ckpt.zip这个包的cpkt文件,始终会报错说读取的cpkt文件无效,只能通过先训练几步,然后调用生成的cpkt文件来evaluate(若使用训练生成的cpkt文件,只需要将CHECKPOINT_PATH设置为装cpkt文件的文件夹即可,CHECKPOINT_PATH=./checkpoint),我查阅了一下,最后调用cpkt的是一个名为slim.evaluation.evaluate_once的函数,这个函数传入的是一个cpkt文件,需要知道的是一般cpkt的文件结构如下(详见博客Tensorflow加载预训练模型和保存模型)
|--checkpoint_dir
| |--checkpoint
| |--MyModel.meta
| |--MyModel.data-00000-of-00001
| |--MyModel.index
在有图结构的情况下,是不需要meta文件的(也许),本来data和index在0.11之前是一起保存为一个后缀直接为cpkt的文件中的,在官方的cpkt文件中也是这样:官方checkpoint,但是在0.11后,cpkt分成两个文件保存了,理论上函数参数也会更新,但是在读取时仍会报错,不知道什么原因。