在自己的数据集上训练Tensorflow目标检测模型

27

经过几天的尝试,我想分享一下我回答这个问题的经验:

我如何使用 TS Object Detection 使用自己的数据集进行训练?


1
你是个牛人,谢谢! - Michael Ramos
2个回答

54
这假定模块已经安装。如果没有,请参考他们的文档免责声明 此答案并不意味着训练目标检测模块的正确唯一方法。这只是我分享我的经验以及对我有效的方法。我愿意接受建议,并在ML方面学到更多,因为我还是新手。 TL;DR
  1. 创建自己的PASCAL VOC格式数据集
  2. 从中生成TFRecords
  3. 配置管道
  4. 可视化
本答案的每个部分都包含相应的编辑(见下文)。阅读每个部分后,请阅读其编辑以进行澄清。每个部分都添加了更正和提示。 使用的工具 LabelImg:用于创建PASCAL VOC格式注释的工具。 1. 创建自己的PASCAL VOC数据集

PS: 为了简单起见,我的答案中所使用的文件夹命名约定遵循Pascal VOC 2012的命名规则

浏览一下2012年5月数据集,你会注意到该文件夹具有以下结构

+VOCdevkit +VOC2012 +Annotations +ImageSets +Action +Layout +Main +Segmentation +JPEGImages +SegmentationClass +SegmentationObject

目前,对以下文件夹进行了修改:

Annotations: 所有图像对应的XML文件都将放置在此处。使用上面建议的工具创建注释。不必担心<truncated><difficulty>标签,因为它们将被训练和评估二进制文件忽略。

JPEGImages: 您实际图像的位置。请确保它们是JPEG类型,因为这是目前支持使用提供的脚本创建TFRecords所需的格式。

ImageSets->Main: 这只是由文本文件组成的简单集合。对于每个类别,都有相应的train.txttrainval.txtval.txt文件。下面是VOC 2012文件夹中aeroplane_train.txt的内容示例。

2008_000008 -1
2008_000015 -1
2008_000019 -1
2008_000023 -1
2008_000028 -1
2008_000033  1

这个结构基本上是图像名称,紧随其后的是一个布尔值,表示对应的对象是否存在于该图像中。例如,图像2008_000008不包含飞机,因此标记为-1,但图像2008_000033包含。

我编写了一个小型的Python脚本来生成这些文本文件。只需遍历图像名称并在它们旁边分配1或-1以表示对象是否存在即可。我通过混洗图像名称在我的文本文件中添加了一些随机性。

{classname}_val.txt文件包括测试验证数据集。可以将其视为训练期间的测试数据。您需要将数据集划分为训练和验证。更多信息可以在这里找到。这些文件的格式与训练文件类似。

此时,您的文件夹结构应如下:

+VOCdevkit +VOC2012 +Annotations --(针对每个图像,生成的注释) +ImageSets +Main --(针对每个类别,生成*classname*_train.txt和*classname*_val.txt) +JPEGImages --(一堆JPEG图像)


1.1 生成标签映射

准备好数据集后,我们需要创建相应的标签映射。 转到models/object_detection/data并打开pascal_label_map.pbtxt

该文件由一个JSON组成,为每个项目分配ID和名称。请修改此文件以反映您所需的对象。


2. 生成TFRecords

如果你仔细查看他们的代码,特别是这, 他们明确地只获取aeroplane_train.txt。对于好奇心强的人,这里是原因。将此文件名更改为任何一个你的类训练文本文件。

确保VOCdevkitmodels/object_detection中,然后你就可以生成TFRecords了。

如果遇到任何问题,请先查看他们的代码。它自我解释并有良好的文档记录。


3. 管道配置

说明应该是自解释的,以涵盖这一部分。样例配置文件可以在object_detection/samples/configs中找到。

对于那些像我一样想要从头开始训练的人,只需确保删除fine_tune_checkpointfrom_detection_checkpoint节点。这是我的配置文件供参考。

从这里开始,您可以继续教程并运行训练过程。


4. 可视化

一定要在训练过程中并行运行 eval,以便能够可视化学习过程。引用 Jonathan Huang 的话:

最好的方法是只需运行 eval.py 二进制文件。我们通常会在训练期间并行运行此二进制文件,将其指向正在训练的检查点所在的目录。eval.py 二进制文件将写入您指定的 eval_dir 中的日志,然后您可以使用 Tensorboard 指向该日志。

您想要看到 mAP 在前几个小时内“起飞”,然后您想要看到何时收敛。如果不查看这些图表,很难确定需要多少步骤。


编辑I(2017年7月28日):

我从未想过我的回答会受到这么多关注,所以我决定回来再审查一下。

工具

对于我的苹果用户同胞们,你们实际上可以使用 RectLabel 进行注释。

Pascal VOC

经过搜寻,我终于意识到trainval.txt 实际上是训练和验证数据集的联合。

请查看他们的官方开发工具包 以更好地了解格式。

标签地图生成

在我写作时,ID 0 代表none_of_the_above。建议你的ID从1开始。

可视化

在运行评估并将tensorboard指向Eval目录后,它会显示每个类别的mAP以及每个类别的表现。这很好,但我也想看到我的训练数据与Eval并行显示。
为此,请在不同的端口上运行tensorboard,并将其指向您的train目录。
tensorboard --logdir=${PATH_TO_TRAIN} --port=${DESIRED_NUMBER}

1
谢谢。最终我也转向了2.7版本,情况变得更好了。 - AruniRC
1
2880X1800肯定太大了。如果你看看image_resizer下的配置文件,对象检测器最终会将每个图像调整为300X300。虽然我输入的图像是618X816,但它仍然可以很好地检测到我想要的类。我建议在运行检测之前先调整图像大小,以查看哪些比例仍然保持对象的良好视觉效果(这也是我所做的)。您还可以调整image_resizer的参数,运行检测并比较结果。 - eshirima
1
@eshirima 谢谢,那么这个调整大小器是否聪明到足以调整原始图像的注释和边界框呢? - Michael Ramos
1
我无法给你一个具体的答案,但在核心中,边界框是对由大多数对象属性/特征组成的像素位置的估计。您看到的最终框实际上是多个紧密包装的框组合在一起的结果。将整个2880X1800输入会导致太多的特征,无法将它们保存在内存中,并且在计算上惩罚,从而导致单层计算需要很长时间。 - eshirima
1
调整大小的想法是找到足够的特征,使它们可以保存在内存中,但不会对计算造成惩罚。理论上,一旦它学习了所有这些特征,它应该也能在更大的图像中找到它们。但处理大帧仍然是计算机视觉中的一个持续问题。 - eshirima
显示剩余21条评论

16
我在Medium上写了一篇关于我的经验以及如何使用Tensorflow训练自己数据集中的对象检测器(具体而言,是一种浣熊检测器)的博客文章。这可能对其他人也有用,可以作为eshirima答案的补充。

2
嘿,谢谢你的建议:) 我看了一下RectLabel。看起来很不错。我会试试的。关于你的第一个问题,num_hard_examples 与难例挖掘器有关。请查看这篇论文以了解更多信息。num_examples 与评估有关。在评估过程中,它会获取图像,您需要指定有多少张图片。他们还使用了 max_eval 来限制评估过程。对于第三个问题:) 哈哈没关系,重要的不是谁先来,而是互相学习。 - Dat Tran
你好,当训练 SSD 时,你是否添加了难负样本?因为论文中提到如果我们添加难负样本,它会表现得更好。 - Shamane Siriwardhana
1
@Yirga 当然可以,但这可能需要一些时间。 - Dat Tran
1
@rambossa 如果您关心这些矩形的稳定性,建议您查看一下ROLO - Dat Tran
1
@ShamaneSiriwardhana 在训练后,我遇到了一些误报检测。这很容易发生,因为模型不能保证始终100%正确,因为_mAP_从未完全收敛为0。关于数据集,我使用了PASCAL,因为它是在[ImageNet](http://image-net.org/index)之前的行业标准,因此有更大的社区支持。 - eshirima
显示剩余14条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接