1. 引言


因项目要求,需要在PocketFlow中添加一套PeleeNet-SSD和COCO的API,具体为在datasets文件夹下添加coco_dataset.py, 在nets下添加peleenet_at_coco.py和peleenet_at_coco_run.py。其中网络结构和backbone等在师兄把项目交付给我之前已经基本完成,所以我主要的工作就是处理COCO的数据(转换成tfrecord文件)和简单更改一些调用的接口。另外PocketFlow中已经包含在VOC上的数据处理,且在检测任务上,VOC和COCO的数据集标注很接近,唯一的区别就是feature_map:

# VOC
feature_map = {
'image/encoded': tf.FixedLenFeature([], dtype=tf.string, default_value=''),
'image/format': tf.FixedLenFeature([], dtype=tf.string, default_value='jpeg'),
'image/filename': tf.FixedLenFeature((), dtype=tf.string, default_value=''),
'image/height': tf.FixedLenFeature([1], dtype=tf.int64),
'image/width': tf.FixedLenFeature([1], dtype=tf.int64),
'image/channels': tf.FixedLenFeature([1], dtype=tf.int64),
'image/shape': tf.FixedLenFeature([3], dtype=tf.int64),
'image/object/bbox/xmin': tf.VarLenFeature(dtype=tf.float32),
'image/object/bbox/ymin': tf.VarLenFeature(dtype=tf.float32),
'image/object/bbox/xmax': tf.VarLenFeature(dtype=tf.float32),
'image/object/bbox/ymax': tf.VarLenFeature(dtype=tf.float32),
'image/object/bbox/label': tf.VarLenFeature(dtype=tf.int64),
'image/object/bbox/difficult': tf.VarLenFeature(dtype=tf.int64),
'image/object/bbox/truncated': tf.VarLenFeature(dtype=tf.int64),
} # COCO
# change filename(string) to image_id(int64) and remove difficult and truncated
feature_map = {
'image/encoded': tf.FixedLenFeature([], dtype=tf.string, default_value=''),
'image/format': tf.FixedLenFeature([], dtype=tf.string, default_value='jpeg'),
'image/image_id': tf.FixedLenFeature([1], dtype=tf.int64), #
'image/height': tf.FixedLenFeature([1], dtype=tf.int64),
'image/width': tf.FixedLenFeature([1], dtype=tf.int64),
'image/channels': tf.FixedLenFeature([1], dtype=tf.int64),
'image/shape': tf.FixedLenFeature([3], dtype=tf.int64),
'image/object/bbox/xmin': tf.VarLenFeature(dtype=tf.float32),
'image/object/bbox/ymin': tf.VarLenFeature(dtype=tf.float32),
'image/object/bbox/xmax': tf.VarLenFeature(dtype=tf.float32),
'image/object/bbox/ymax': tf.VarLenFeature(dtype=tf.float32),
'image/object/bbox/label': tf.VarLenFeature(dtype=tf.int64),
}

所以讲道理,即使对TensorFLow并不熟,完成这些API的难度也不大,确实也只用了半天就写完了,不过之后的调试用了半个月

2. 程序挂起无输出


最开始是训练时一开始程序就卡住,和挂起差不多,而且也没有报错信息,运行截图如下:

因为TensorFlow的计算图机制导致在session.run()之前,所有的输出都是node和tensor的信息,所以个人觉得debug比较困难。尤其是你一上来就整个什么都不输出,我确实有点懵逼,不知道怎么做。上Google搜了搜TensorFlow 卡住 挂起等关键词,基本上有两种:

  • TensorFlow计算和数据读取是异步的,读不到数据导致进程挂起,在代码中加上tf.train.start_queue_runners(sess=sess)开启队列啥的
  • 计算图中有新增节点的操作,导致每次推导时内存占用越来越多,最后进程挂起

但比较气人的是,师兄写的PeleeNet-SSD和VOC的API就没有这种情况,而且我随便改batchsize都可以正常跑起来,所以网络结构应该没问题。至于队列,因为用的是dataset那一套的API,两者也没什么相关,加上之后还是没卵用。不过peleenet那块没问题,那大概是读取数据的API有问题。

于是我一行一行的对比(PyCharm Compare With...)后来新增的脚本和师兄之前写的在VOC上的那套,检查了3遍,是真的看不出有什么问题...然后又检查了将COCO数据集转换为tfrecord的脚本,同上,数据应该没错。不过唯一的收获就是发现bbox的坐标计算有错,导致gt有问题,随后改过来了。后来想想,如果gt是错的话,训练的模型准确率再高,预测时还是gg,这bug也挺难发现的

最后求助于师兄,他给我演示了一下怎么用session.run()调试程序,找出程序卡在哪里。他首先判断因为读不到数据,所以排除peleenet_at_coco.py和peleenet_at_coco_run.py的问题(xxx_run.py几个脚本基本都一样,也不会出什么错,另外一个主要定义的网络结构,是读取数据之后的操作,所以这两个都不用怎么检查)。之后着重调试coco_dataset.py,他找到把数据传入网络的最后一步,是一个定义在coco_dataset.py的函数parse_fn,然后注释掉中间的代码,只原样返回最初的输入,发现能用session.run()读到数据之后再逐步解开剩下代码的注释。这样卡在那一步就能说明哪一块有问题了,最后发现是卡在了数据预处理preprocess_image()

我感觉有点开窍了,但是自己之后又调试了下,发现加上预处理的部分,数据也能读出来...最后的结论是不加预处理数据可以读,加上之后有时可以读,有时会卡住,甚至有点随机的感觉。把预处理换成了简单的resize()统一图片大小之后,batchsize大点就卡的早点,小的话就晚点。那真的有意思,只能接着看预处理部分了。

3. 报错:Reduction axis 0 is empty in shape [0, 5028]


预处理主要包括:

  • 随机扭曲颜色
  • 随机裁剪(bbox坐标值相应变化)
  • 随机水平翻转
  • 缩放到固定尺寸
  • 减去ImageNet训练集的RGB均值

PocketFlow项目中的数据预处理(数据增强)来自HiKapok/SSD.TensorFlow, 这哥们代码写的很好,还有单元测试,属实良心。另外知乎上也有两篇相关的文章:Inside TF-Slim(13) preprocessing(图像增强相关)SSD-TensorFlow 源码解析,以后认真学习一下。

仅保留缩放操作之后,运行COCO训练的脚本,程序报以下错误(VOC仍无问题):

google之后也没找到什么有参考价值的答案,只能看预处理的代码了。因为刚接触目标检测,TensorFLow也用的不熟,读的比较吃力,不过幸好有VOC的单元测试,可以把预处理之后的图像保存到本地,还能在图片上直接绘制bbox和label,稍微修改之后就能用在COCO上了,效果如下:

测试时发现,COCO保存若干张图片后会卡住,而VOC能一直运行。现在终于能确定是数据的问题了,碰巧在COCO保存的图片中发现有少数图片没有bbox框,大概知道问题出在哪里了。看了看之前检查数据的脚本,妈的居然写错了,修改之后,发现了1020张没有label和bbox标注的图片,根据image_id在COCO的instances_train2014.json文件的images列表找到了这些图片,然而在json文件的annotations列表中居然搜不到这些图片的标注!(如:COCO_train2014_000000542614.jpg)清除tfrecord文件里的这些图片的相关数据之后,在COCO上也能正常训练了!

所以调用argmax()时,这些图像的bbox为[],就会出现shape的维度为0而报错的情况。而程序卡住也是因为图像增强时处理到了这些图片,batchsize越大,就越容易遇到(1020/118230)。之前因为输出过自己转换的tfrecord的文件结构,而且随机抽取的图片也能正常显示,所以就一味的相信数据没有问题,还是没有考虑全面,所以浪费了很多时间。

判断tfrecord文件是否含不带bbox的图片的代码

import os
import tensorflow as tf file_list = tf.gfile.Glob(os.path.join('/DATA/coco/tfrecords', 'val-?????-of-?????'))
i = 0
count = 0
for file in file_list:
for string_record in tf.python_io.tf_record_iterator(file):
example = tf.train.Example()
example.ParseFromString(string_record) i += 1
image_id = example.features.feature['image/image_id'].int64_list.value
xmax = example.features.feature['image/object/bbox/xmax'].float_list.value
# xmin = example.features.feature['image/object/bbox/xmin'].float_list.value
# ymax = example.features.feature['image/object/bbox/ymax'].float_list.value
# ymin = example.features.feature['image/object/bbox/ymin'].float_list.value if xmax == []:
print(image_id)
count += 1
print(file, 'has been checked.') print(i, 'images have been checked.')
print(count, 'annotations without bbox.')

4. 总结


  1. TensorFlow框架虽然有限制,但调试还是可以调试的,首先要熟悉程序的结构,弄清参数传递的过程
  2. 不要纠缠细节,调试的目的是快速且理性的判断bug的位置
  3. 写程序时要写单元测试,调试时会方便许多
  4. TensorFLow, to make your life difficult:)

[PocketFlow]解决TensorFLow在COCO数据集上训练挂起无输出的bug的更多相关文章

  1. (2) 用DPM(Deformable Part Model,voc-release4.01)算法在INRIA数据集上训练自己的人体检測模型

    步骤一,首先要使voc-release4.01目标检測部分的代码在windows系统下跑起来: 參考在window下执行DPM(deformable part models) -(检測demo部分) ...

  2. CaffeExample 在CIFAR-10数据集上训练与测试

    本文主要来自Caffe作者Yangqing Jia网站给出的examples. @article{jia2014caffe, Author = {Jia, Yangqing and Shelhamer ...

  3. 解决VS2010中在项目上右键鼠标,无“添加STS引用”菜单的问题

    解决方法:将Windows Identity Foundation SDK文件夹C:\Program Files (x86)\Windows Identity Foundation SDK\v3.5\ ...

  4. [PocketFlow]解决在coco上mAP非常低的bug

    1.问题 继上次训练挂起的bug后,又遇到了现在评估时AP非常低的bug.具体有多低呢?Pelee论文中提到,用128的batchsize大小在coco数据集上训练70K次迭代后,AP@0.5:0.9 ...

  5. Pascal VOC & COCO数据集介绍 & 转换

    目录 Pascal VOC & COCO数据集介绍 Pascal VOC数据集介绍 1. JPEGImages 2. Annotations 3. ImageSets 4. Segmentat ...

  6. 【Tensorflow系列】使用Inception_resnet_v2训练自己的数据集并用Tensorboard监控

    [写在前面] 用Tensorflow(TF)已实现好的卷积神经网络(CNN)模型来训练自己的数据集,验证目前较成熟模型在不同数据集上的准确度,如Inception_V3, VGG16,Inceptio ...

  7. TensorFlow学习笔记——LeNet-5(训练自己的数据集)

    在之前的TensorFlow学习笔记——图像识别与卷积神经网络(链接:请点击我)中了解了一下经典的卷积神经网络模型LeNet模型.那其实之前学习了别人的代码实现了LeNet网络对MNIST数据集的训练 ...

  8. 深度学习笔记 (二) 在TensorFlow上训练一个多层卷积神经网络

    上一篇笔记主要介绍了卷积神经网络相关的基础知识.在本篇笔记中,将参考TensorFlow官方文档使用mnist数据集,在TensorFlow上训练一个多层卷积神经网络. 下载并导入mnist数据集 首 ...

  9. 在ubuntu1604上使用aria2下载coco数据集效率非常高

    简单的下载方法: 所以这里介绍一种能照顾大多数不能上外网的同学的一种简单便捷,又不会中断的下载方法:系统环境: Ubuntu 14.04 方法: a. 使用aria2 搭配命令行下载.需要先安装: s ...

随机推荐

  1. Spring8中lambda表达式的学习(Function接口、BiFunction接口、Consumer接口)

    代码重构,为了确保功能的等效性,梳理代码时,发现如下代码: public SingleRespTTO fundI(SingleReqTTO request) throws Exception { re ...

  2. video object detection

    先说一下,我觉得近两年最好的工作吧.其他的,我就不介绍了,因为我懂得少. 微软的jifeng dai的工作. Deep Feature Flow   github: https://github.co ...

  3. Javascript和android原生互调

    最近在做原生和js端的互调的功能,自己改了个demo,给大家讲解下. 先上js代码 <!DOCTYPE html> <html> <head> <meta c ...

  4. Python 学习笔记(八)Python列表(一)

    列表基本操作 列表(list)定义  列表是Python中的一种对象类型,也是一种序列 对象类型:list 表示方法:[ ] python 列表中的元素可以是任何类型的对象 >>> ...

  5. ZooKeeper下载安装(Windows版本)

    进入Apache ZooKeeper官方网站进行下载,https://zookeeper.apache.org/releases.html 这里我们选择zookeeper-3.4.12版本进行下载 百 ...

  6. Zabbix——异常问题处理

    报错: zabbix server is not running: the information displayed may not be current 解决: selinux关闭.开启selin ...

  7. Centos防火墙的配置

    Selinux的三种模式:enforcing,passive,disable 临时更改模式:setengorce 1|0        1:enforcing,   0:passive [root@C ...

  8. JSP/Servlet开发——第五章 使用分层实现业务处理

    1.JNDI(Java Naming and Directory Interface)Java命名和目录接口: ●JNDI:是一个有关应用序设计的 API 为开发人员提供了查找和访问各种命名和目录服务 ...

  9. 20.2 解析与序列化【JavaScript高级程序设计第三版】

    JSON 之所以流行,拥有与JavaScript 类似的语法并不是全部原因.更重要的一个原因是,可以把JSON 数据结构解析为有用的JavaScript 对象.与XML 数据结构要解析成DOM 文档而 ...

  10. pads怎么高亮网络

    pads怎么高亮网络 选择完整个网络----再按CTRL+H 就高亮了. 取消高亮是,选择需要取消高亮的整个网络,按 CTRL+U 就取消了. PADS在生成Gerber时过孔盖油设置方法 PADS2 ...