EfficientDet训练数据集anchor设定教程101

本文由小肉包老师原创,转载请注明出处,来自腾讯、阿里等一线AI算法工程师组成的QQ交流群欢迎你的加入: 1037662480

上一篇文章我们传授了大家如何使用darknet训练自己的数据集,使用YoloV4的模型,不过最近很火的EfficientDet模型精度超越YoloV4(在D4+),尽管它使用了更大的输入尺寸。我们还是希望来尝试一下efficientdet吊炸天的检测能力。事实上,社区开源的efficientdet很多人无法复现原作者的coco检测结果,原因是lr比较难调。笔者自己尝试下来,发现lr确实很重要,但对于自己的数据集,anchor的设定才是重中之重。本文将从anchor这么一个角度,教大家如何来调efficientdet,同时看完本文,如果你是一个目标检测小白,我估计你应该也入门目标检测了。

本文将cover的内容包括:

  • 单阶段算法anchor的原理(白话图文版);
  • 如果debug你的anchor设定(尽量cover尽可能多的ground truth 框);
  • 在EfficientDet中通过调节anchor使得你的数据集检测能力提高一个等级。

可视化anchor

anchor是什么?很多人在这里会画一大堆的图,我不想这么做,尽管图片更加直观,我直接告诉你一个矩阵:

INFO 05.12 14:35:17 anchor_inspector.py:204: anchors: [[   2.88       2.88       5.12       5.12   ][   2.88       1.76       5.12       6.24   ][   1.76       2.88       6.24       5.12   ]...[ 734.22217  734.22217 1185.7778  1185.7778 ][ 734.22217  508.4443  1185.7778  1411.5557 ][ 508.4443   734.22217 1411.5557  1185.7778 ]]

这是我log出来的一系列anchor,它每一行四个坐标代表的就是一个框(xywh), 它总共有:

anchors shape: (196416, 4), ann shape: (2, 4)

196416个anchor,如果把这些anchor全部画到图片上就长这样:

什么?这怎么什么都么有?原因很简单,因为框实在是太多了,直接就把图片填满了。大家不要脑补这绿色背后是啥,它就是一张普通的图片。

接着我们接下来会怎么搞? 既然anchor这么多,我如何确定我需要的anchor呢?它就隐藏在这19w里面的一两个 (大家仔细看上图的白色框,实际上就是groud truth)这是一个极小目标检测的任务。如何找呢? 算法也很简单:

a. 我知道了anchor,我也知道了annotation,我接下来是不是要算一下他们之间的overlap;

b. 选择overlap最大的anchor,不就是我们需要的anchor了吗?

对应的算法也很简单,为了让大家耐心的看完这篇文章,我再最后的时候再放上所有的代码。那我们就来计算一下,看看能不能filterout我们需要的anchor,并把它画在图片上,和ground truth一起。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5Xkfvcqe-1590051993407)(https://i.loli.net/2020/05/12/MnDCY53oUGEiplT.png)]

看到上图,大家可以发现,淡绿色的是anchor(也就是我们的上面生成的19w的box里面的一个),我们找到一个和左边的groundtruth契合的框,而右边的没有找到。

这意味着什么?

至少意味着两点:

  • 我们生成的anchor不是最优的,它没有尽可能的囊括最多的ground truth;
  • 如果这样的anchor用于训练,会导致这个地方无任务背景,且浪费掉了大量的正例框,毫无疑问这样的网络无法学习到这么小物体的目标,不管你的检测器多强,都会漏检。

针对这样的问题,我们是不是需要想办法,对自己的数据集,去计算适合自己的anchor设定呢?

## 一劳永逸计算自己数据集的anchor

首先大家要明确自己当前要解决的问题是啥,anchor只和图片的shape有关,不同的图片同样的shape,则anchor是一样的,我们如何才能保证这些box能够尽可能的囊括所有的gt box呢?

能想到的第一个方法就是聚类,对box进行聚类,有同学会问了,你聚类之后呢?如何生成那19w个框呢?

这个疑问非常好,我们还没有告诉大家那19w个框到底是如何产生的。先给大家上anchor 生成的代码:

boxes_all = []
for stride in self.strides:boxes_level = []for scale, ratio in itertools.product(self.scales, self.ratios):if image_shape[1] % stride != 0:raise ValueError('input size must be divided by the stride.')base_anchor_size = self.anchor_scale * stride * scaleanchor_size_x_2 = base_anchor_size * ratio[0] / 2.0anchor_size_y_2 = base_anchor_size * ratio[1] / 2.0x = np.arange(stride / 2, image_shape[1], stride)y = np.arange(stride / 2, image_shape[0], stride)xv, yv = np.meshgrid(x, y)xv = xv.reshape(-1)yv = yv.reshape(-1)# y1,x1,y2,x2boxes = np.vstack((yv - anchor_size_y_2, xv - anchor_size_x_2,yv + anchor_size_y_2, xv + anchor_size_x_2))boxes = np.swapaxes(boxes, 0, 1)boxes_level.append(np.expand_dims(boxes, axis=1))# concat anchors on the same level to the reshape NxAx4boxes_level = np.concatenate(boxes_level, axis=1)boxes_all.append(boxes_level.reshape([-1, 4]))anchor_boxes = np.vstack(boxes_all)
anchor_boxes = torch.from_numpy(anchor_boxes.astype(dtype)).to(device)
anchor_boxes = anchor_boxes.unsqueeze(0)

这部分代码取自keras-retinanet,完善于Yet-Another-EfficientDet,我们在这里做一个简单的讲解。

这里只有3个很重要的变量:

strides: [8, 16, 32, 64, 128]
scales: [0.1        0.25       1.25992105]
ratios: [(0.7, 0.7), (1.4, 0.7), (0.7, 1.4)]

其实最核心的是这行代码:

x = np.arange(stride / 2, image_shape[1], stride)
y = np.arange(stride / 2, image_shape[0], stride)
xv, yv = np.meshgrid(x, y)

知道imageshape, 也就知道了最里面的meshgrid之后的size有多大。

比如imageshape是(1024, 1024),那么stride是8 的时候最里面的box数目就是: 128x128=16384:

stride 8 -> 128*128 -> 128*128 * 3 * 3 = 147456
stride 16 -> 64*64 -> 64*64 *3*3       = 36864
stride 32 -> 32*32 -> 32*32 *3*3       = 9216
stride 64 -> 16*16 -> 16*16 *3*3       = 2304
stride 128 -> 8*8 -> 8*8 *3*3          = 576

所有总共的anchor数目应该是:

147456 + 36864 + 9216 + 2304 + 576 = 196416

这和我们上面直接输出的anchor完全吻合!

很多同学可能还没有看懂上面的具体演示和计算,如果你还没有搞懂具体计算方法,可以加入我们的社区,一起来交流:

http://t.manaai.cn

刚才说道如何计算我们的anchor?也就是需要聚类,那么这里面就有一个问题了,既然是聚类,我聚类成几类比较合适呢?这个类别和我的模型是否有关系呢?

聚类的列别数目,和我们需要的anchor有关,这个anchor的设计,实际上和网络的结构没有多大关系,唯一有关系的就是我们需要多少level的特征,就设置多少个不同比例的anchor。至于这背后的深刻思想内涵,谁知道呢?我们就按照大家都喜欢的方式来吧。

我们会把anchor可视化和聚类计算的代码都放在文章的最下面,大家可以跑一下,计算你数据集的最佳anchor。但有一句话必须要得说:

anchor的设计对于网络的影响非常大,但是只要你设置的合理,网络一般都能handle,一般直接聚类计算出来的anchor并不一定是最优的。你可能需要手动的去调节,比如小的物体没有匹配到anchor,我就把最小的那个scale减小。

又深深的上了一课,原来调参工程师并不简单没有对问题深刻的洞见无法解决我们的问题。

最后这里贴一张图,很多人训练efficientdet应该是没有办法很好的训练好的,除非他的数据集比较中等,也就是说没有太小的物体,也没有太大的物体。

那么这个时候你就需要考虑到anchor的设计啊,你想啊,你的anchor在训练的时候都匹配不大,你拿啥去训练,全给你当背景了。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Zpx6DPxL-1590051993411)(https://i.loli.net/2020/05/13/ESePNh2mlviWyDu.png)]

正常的anchor匹配。如果你能看到你的anchor,说明你匹配成功了。

当然这里的匹配不可能每个ground truth都能找到anchor,但是你得保证绝大部分是有的,其他的,随缘。

## 用新的anchor训练efficientdet

笔者在没有设计anchor之前,是懵逼的,因为coco的anchor直接拿过来根本没法用呀,豆大的目标无法检测,这还是霸榜多年的哪个efficientdet吗?

最后新的anchor训练出来的之后的检测效果,各位看官可以参考参考。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Jr7CX5mQ-1590051993413)(https://i.loli.net/2020/05/18/DCvjqIxX6OkoniZ.png)]

当然,这也仅供参考,我们希望大家可以依照这个教程可以在自己的数据集上训练出一个比较好的结果。

最后分享几点在训练测试,调节efficientdet时几点经验, 以及这个检测器本身存在弊端:

  • 没有什么算法是万能的,这个highly hyper paramed 并且连lr都会严重影响训练效果的检测器非常的脆弱,一点某个地方不对,你就可能得到一个废掉的结果,最严重的就是本文提到的这个anchor;
  • 事实证明,不管你的anchor设计的多么合理,多么精妙,最终这个模型本身无法逃离它的致命缺陷:检测不稳。这里说的不稳,包括漏检和概率不稳,这对于工业应用是致命的。具体来说就是,前后两张几乎一样的图片(video的相邻两帧),第一针可能检测到了,而下一帧就漏,还有就是同一个物体,前面一帧的概率是90%,下一帧就可能是10%.

当然这也可能是由于achor还不是最优化导致的,但对于一个检测器来讲,你的数据以增加你就要重新计算anchor,甚至是重新训练模型,那还有什么意义呢?

代码

我们所有的代码托管在MANA AI,如果你看完本文觉得不错,一定记得三联啊老铁!!点赞,转发,评论走起!

本文中的数据集为非公开数据集,但anchor的配置可视化是公开的,大家可以点击链接去制作自己的anchor:

https://github.com/manaai-cn/anchor_computation_tool

我们的AI交流社区:

http://t.manaai.cn

MANA平台:

http://manaai.cn

广告时间

接下来是广告时间。如果你想学习人工智能,对前沿的AI技术比较感兴趣,可以加入我们的知识星球,获取第一时间资讯,前沿学术动态,业界新闻等等!你的支持将会鼓励我们更频繁的创作,我们也会帮助你开启更深入的深度学习之旅!

EfficientDet训练数据集anchor设定教程101相关推荐

  1. 教程:Yolo5训练自己的数据集以及安装教程

    教程:Yolo5训练自己的数据集以及安装教程 [一]准备相关文件 1.Anaconda 2.Yolo5 3.权重文件 [二]环境搭建 1.在Anaconda中为Yolo5创建一个环境 2.Yolo5文 ...

  2. 使用CycleGAN训练自己制作的数据集,通俗教程,快速上手

    总结了使用CycleGAN训练自己制作的数据集,这里的教程例子主要就是官网给出的斑马变马,马变斑马,两个不同域之间的相互转换.教程中提供了官网给的源码包和我自己调试优化好的源码包,大家根据自己的情况下 ...

  3. 基于深度学习的瓶子检测软件(UI界面+YOLOv5+训练数据集)

    摘要:基于深度学习的瓶子检测软件用于自动化瓶子检测与识别,对于各种场景下的塑料瓶.玻璃瓶等进行检测并计数,辅助计算机瓶子生产回收等工序.本文详细介绍深度学习的瓶子检测软件,在介绍算法原理的同时,给出P ...

  4. 基于深度学习的农作物叶片病害检测系统(UI界面+YOLOv5+训练数据集)

    摘要:农作物叶片病害检测系统用于智能检测常见农作物叶片病害情况,自动化标注.记录和保存病害位置和类型,辅助作物病害防治以增加产值.本文详细介绍基于YOLOv5深度学习模型的农作物叶片病害检测系统,在介 ...

  5. 基于YOLOv5的停车位检测系统(清新UI+深度学习+训练数据集)

    摘要:基于YOLOv5的停车位检测系统用于露天停车场车位检测,应用深度学习技术检测停车位是否占用,以辅助停车场对车位进行智能化管理.在介绍算法原理的同时,给出Python的实现代码.训练数据集以及Py ...

  6. 水果新鲜程度检测系统(UI界面+YOLOv5+训练数据集)

    摘要:水果新鲜程度检测软件用于检测水果新鲜程度,利用深度学习技术识别腐败或损坏的水果,以辅助挑拣出新鲜水果,支持实时在线检测.本文详细介绍水果新鲜程度检测系统,在介绍算法原理的同时,给出Python的 ...

  7. 独家 | 如何改善你的训练数据集?(附案例)

    作者:Pete Warden 翻译:申利彬 校对:丁楠雅 本文约6800字,建议阅读10分钟. 本文作者基于自身项目经验阐述训练数据的重要性并分享了一些改进的实用技巧. Lisha Li 摄 这张幻灯 ...

  8. Python机器学习:KNN算法03训练数据集,测试数据集train test split

    示例代码 首先引入相关包 import numpy as np import matplotlib.pyplot as plt from sklearn import datasets import ...

  9. Ember恶意软件数据集的使用教程

    2018年4月份,网络安全公司Endgame发布了一款名为EMBER的大型开源数据集.EMBER是一个包含了100多万种良性和恶意PE文件(Windows可执行文件)集合,这是一种常见的恶意软件隐藏格 ...

最新文章

  1. Ubuntu: 为firefox安装flash插件
  2. SharePoint 2010 使用自定义aspx页面替换列表默认的新建(NewForm.aspx),查看(DispForm.aspx)和编辑(EditForm.aspx)页面...
  3. Property Exercise
  4. java集合根据值排序_Java 8:对集合中的值进行排序
  5. .net framework 4.0 安装失败解决办法
  6. 机器学习面试之偏差方差
  7. 设计模式-行为型模式-责任链模式
  8. python --面向对象
  9. python elasticsearch模块_Python3 操作 elasticsearch
  10. 如何解决string转CString乱码问题?
  11. 编译运行BSR/bench源码
  12. 是因为Session只能让服务器在一次连续的会话中记住你,而Cookie是记住浏览器一段时间...
  13. 6月29 Electron的第一课
  14. 人工智能技术发展综述
  15. Ubuntu 18.04 开机开启小键盘数字键numlock灯
  16. 浅谈Unity的渲染优化(1): 性能分析和瓶颈判断(上篇)
  17. 四六级重要单词(三)
  18. Trello中的Scrum
  19. 海思[hi3531]编译环境搭建(针对用于编译程序不制作内核和系统的开发者)
  20. React教程(二):React组件基础

热门文章

  1. 字节CEO张一鸣卧底公司群2天,怒斥员工摸鱼
  2. 转:成长,就是不断打破认知
  3. PS自学之图像/打印大小
  4. 浙江大学报考点网上确认所需上传电子照片及材料的标准
  5. [yolov5] yolo的数据标签格式
  6. pygame中精灵的方法详解
  7. 如何将PDF中的A3页面裁剪为2个A4的PDF文档?
  8. CVPR 2021 | 何恺明等人新作!深入探究无监督时空表征学习
  9. html5 自动 幻灯片,HTML5幻灯片演示系统免费版
  10. 使用grub实现虚拟软盘