大家好,又见面了,我是你们的朋友全栈君。
深度学习中,为了提高模型的精度和泛化能力,往往着眼于两个方面:(1)使用更多的数据(2)使用更深更复杂的网络。
** 一、什么是负样本
** 负样本是指不包含任务所要识别的目标的图像,也叫负图像(Negtive Image)。以识别限速牌为例,如下所示,左图包含限速牌,为正样本,右图不包含限速牌,为背景图,即负样本。
正样本
负样本
2.为什么要训练负样本
训练负样本的目的是为了降低误检测率、误识别率,提高网络模型的泛化能力。通俗地讲就是告诉检测器,这些“不是你要检测的目标”。
3.Faster R-CNN、SSD、YOLO等神经网络模型中的负样本
例如在Faster R-CNN中,在RPN阶段,会根据backbone生成的特征图上的每一点,按照不同尺寸、不同长宽比构建很多的候选锚框。这些锚框按照与Ground Truth box的交并比,选择特定阈值进行分类,比如IOU>0.7的锚框,被视为正锚框,也就是正样本,IOU<0.3的被视为负锚框,也就是负样本。通常负样本的数量会远远超过正样本,因此为了平衡类别比例,提高模型精度,常通过Focal Loss方法或hard example mining算法来恰当地利用正、负样本计算Clasification Loss与regresion Loss,并进行反向传播。因此网络模型中的负样本与负图像是不一样的,不能完全同等看待。
4.如何收集负样本
可以通过下面两种方式收集负样本:
采用本任务场景的不包含目标物体的背景图像,例如你的目标是识别某园区内的行人,那么所有本园区内不包含行人的图片都视作负样本。不要使用不属于本任务场景的负图像,因为其对检测器的性能影响不大。 测试图像中被识别错误的目标所在区域。(通常对原图像进行裁剪,使得裁剪下来的图像只包含误识别的物体,而不包含目标)
5.负样本的标签文件
用于目标检测任务的标签通常是xml文件,在xml文件中没有目标位置相关的节点,只有文件名,文件路径、图片宽度、高度、通道数等信息,这就是负样本的标签文件。关于负样本的标签文件的生成方式,可以参考博客:https://blog.csdn.net/dulingwen/article/details/89669928
6.如何训练负样本
将正负样本集及其标签作为训练集送入模型训练即可。
注意:正负样本必须放在一起训练,不能单独训练负样本,否则经过训练,网络会把所有的图像都识别为背景。正负样本的比例最好为1:1到1:2左右,数量差距不能太悬殊,特别是正样本数量本来就不太多的情况下。
尝试方法一:直接对误检的图像生成一个空的xml文件。(文件中没有任何对象) 训练结果:由于xml文件中没有任何正样本对象,所以网络无法学习到背景信息,使用训练后的模型测试误检的图像,依然会产生误检。(这里网上有人说即使没有正样本,SSD网络在训练时也会产生负样本,本人测试,当整幅图像没有任何正样本时,网络学习不到任何信息,训练时loss=0)
尝试方法二:误检的图像中含有正样本对象,但不是误检的类别。(例如:该图像中人物类别出现误检,但对该图像进行训练时只标注了一个汽车类别,而没有增加人物的正样本类别) 训练结果:这种情况下,对网络进行训练时,会产生loss,并且训练后的模型,不会再把误检图像中的背景误检为人物。
7.怎样消除误检——加强检测器
把使用正样本训练好的模型拿来进行测试,此时会得到一些被错误识别的图片。把这些图片收集起来作为负样本加入到正样本集(如果图片中同时包含误识别物体和目标,可以将图像裁剪,裁剪后的图像包含误识别物体而不包含目标并尽量覆盖原图大部分区域,然后再将其分辨率resize回原图大小),组成新的训练集,送入模型进行训练。 如果负样本的来源只有误识别的图片,那么由于误识别的图片往往占少数,可以利用图像增强(如高斯滤波、对比度增强、锐化、平滑等)的方法扩充负图像数量至和正样本数量相同,并组合在一起。将这样得到的训练集送入模型进行训练,经过若干个epoch,当Loss收敛到稳定值时,再次测试原来的出现误识别的图像你会发现误识别现象基本消失了,并且类似原来误识别的场景将会被正确识别。
下面是扩充负样本数量的代码:
代码语言:javascript复制import cv2
from imgaug import augmenters as iaa
import numpy as np
import os
imgdir = '/home/dulingwen/Pictures/pic1/'
imgsave_dir = '/home/dulingwen/Pictures/pic2/'
#do the gaussian blur transform
BLUR_ARG = 2
for i_blur in range(100*BLUR_ARG):
for jpgfile in os.listdir(imgdir):
jpgname = os.path.splitext(jpgfile)[0]
img = cv2.imread(imgdir jpgname '.jpg')
blurer = iaa.GaussianBlur(i_blur/100)
img_aug = blurer.augment_image(img)
cv2.imwrite(imgsave_dir jpgname '_blur_' str(i_blur) '.jpg', img_aug)
#sharp the images in different arguments of alpha and lighness
ALPHA = np.linspace(0,0.5,20)
LIGHTNESS = np.linspace(0.5,1.25,20)
for i_alpha in ALPHA:
for i_lightness in LIGHTNESS:
for img_file in os.listdir(imgdir):
img_name = os.path.splitext(img_file)[0]
img = cv2.imread(imgdir img_name '.jpg')
sharp = iaa.Sharpen(alpha=i_alpha, lightness=i_lightness)
img_aug = sharp.augment_image(img)
cv2.imwrite(imgsave_dir img_name '_sharp_' str(int(10000*i_alpha)) '_' str(int(10000*i_lightness)) '.jpg', img_aug)
二、解决目标检测中的难分样本(漏检测与误检测问题)
1、SRGAN
论文题目:Photo-Realistic Single Image Super-Resolution Using a Generative Adversarial 论文链接:https://arxiv.org/abs/1609.04802 论文代码:https://github.com/JustinhoCHN/SRGAN_Wasserstein 超分辨率重建就是将低分辨率图像恢复成对应的高分辨率图像。但是由于低分辨率图像信息的缺失,这是一个病态的求逆问题尤其是在恢复的倍数较高的时候。传统的方法考虑加入一些先验信息以恢复高分辨率图像(如插值法)还有基于回归方法的随记森林也可以用于超分问题稀疏学习,CNN在超分上也取得了非常好的效果,特别是CNN,使得超分已经可以达到实时应用。 作者用sub-pixel网络作为生成网络,用VGG作为判别网络构建GAN得到了非常好的结果,但这个用的是逐像素差作为损失函数。之后作者尝试了自己提出的感知损失函数作为优化目标,虽然PSNR和SSIM不高,但是视觉效果都要优于其他网络,避免了其他方法的过度平滑的特性。 主要有两点: 提出的SRResNet取得了state-of-art的结果,将感知损失引入GAN,实现了4倍超分辨率重建。
2、ASDN
论文题目:Hard Positive Generation via Adversary for Object Detection 论文地址:https://arxiv.org/pdf/1704.03414.pdf 论文代码:https://github.com/xiaolonw/adversarial-frcnn ASDN网络使用RoI池层提取的功能作为输入图像补丁。 ASDN网络比预测遮挡/退出掩码,然后将其用于丢弃特征值并传递到Fast-RCNN的分类塔。对抗空间丢弃网络(ASDN),它学习如何封闭给定的目标,使得FRCN难以对其进行分类。我们在本文中考虑的第二种类型的生成是变形。在这种情况下,我们提出了对抗空间变换网络(ASTN),它学习如何旋转物体的“部件”,使其难以被检测器识别。通过与这些网络的竞争和克服障碍,FRCN学会以鲁棒的方式处理物体遮挡和变形。请注意,所提出的网络ASDN和ASTN在训练期间与FRCN一起同时学习。联合训练能防止检测器对固定生成的特征产生过拟合。 相比于在输入图像上产生遮挡和变形,我们发现在特征空间上的操作更有效率。因此,我们设计对抗网络来修改特征,使目标变得更难识别。请注意,这两个网络仅在训练过程中应用才能改进检测器。我们将首先单独介绍ASDN和ASTN,然后在统一的框架中将它们组合在一起。在RoI-pooling层之后获得每个前景目标候选区域的卷积特征。我们使用这些基于区域的特征作为对抗网络的输入。对于一个目标的特征,ASDN将尝试生成一个掩码,指示要丢弃的特征的哪些部分(分配零),以便检测器无法识别目标。对抗空间变换网络(ASTN) 我们现在介绍对抗空间变换网络(ASTN)。我们的关键思想是在目标特征上创建变形,并使检测器的目标识别变得困难。我们的网络建立在[14]中提出的空间变换网络(STN)上。 在他们的工作中,STN被提出来使特征变形,使分类更容易。而我们的网络正在完成相反的任务。通过与我们的ASTN网络竞争,我们可以训练一个更好的对变形具有鲁棒性的检测器。 STN概述。空间变换网络[14]有三个部分:定位网络,网格生成器和采样器。对于输入的特征图,定位网络将估计要变形的量(例如,旋转度,平移距离和缩放因子)。这些变量将被用作在特征图上的网格生成器和采样器的输入。输出是变形的特征图。请注意,我们只需要了解定位网络中的参数。STN的关键贡献之一是使整个过程是可微分的,从而可以通过反向传播直接优化分类目标的定位网络。有关更多技术细节,请参阅[14]。 对抗STN。在我们的对抗空间变换网络中,我们专注于特征图旋转。也就是说,在RoI-pooling层后给出了一个特征图作为输入,我们的ASTN将学习旋转特征图,使其更难识别。我们的定位网络由3个完全连接的层组成,其中前两层使用来自ImageNet预训练网络的fc6和fc7层进行初始化,就像我们的对抗空间丢弃网络一样。 我们共同训练ASTN和Fast-RCNN检测器。对于训练检测器,类似于ASDN中的过程,RoI-pooling之后的特征首先由ASTN进行转换,并转发到较高层以计算SoftMax损失。为了训练ASTN,我们优化它以便检测器将前景目标分类为背景类。与ASDN不同,由于空间变换是可以微分的,我们可以直接使用分类损失来对ASTN的定位网络中的参数进行回溯和微调。 实现细节。在我们的实验中,我们发现限制ASTN的旋转度非常重要。否则,很容易将目标上下颠倒,这在大多数情况下是最难识别的。我们将旋转度限制在顺时针和逆时针10度以内。相比于沿同一方向旋转所有特征图,我们将通道尺寸上的特征图划分为4个块,并为不同的块估计4个不同的旋转角度。由于每个通道对应于一种类型的激活特征,旋转通道分别对应于导致变形的不同方向的物体的旋转部分。我们还发现,如果我们对所有特征图使用一个旋转角度,ASTN将经常预测最大的角度。通过使用4个不同的角度而不是一个,我们增加了任务的复杂性,防止网络预测琐碎的变形。
2.3 对抗融合 两个对抗网络ASDN和ASTN也可以在同一个检测框架中组合在一起并联合训练。由于这两个网络提供不同类型的信息。通过同时竞争这两个网络,我们的检测器变得更加健壮。 我们将这两个网络以顺序的方式组合到Fast-RCNN框架中。 如图4所示,在RoI-pooling之后提取的特征映射首先进入到我们的ASDN,ASDN会删除一些激活值。修改后的特征由ASTN进一步变形。 ASDN分析。我们比较我们的对抗空间丢弃网络与使用AlexNet架构的训练中的各种丢弃/遮挡策略。我们尝试的第一个简单基线是RoI-Pooling后的特征的随机空间丢弃。为了公平的比较,我们屏蔽了与ASDN网络中相同数量神经元的激活值。如表2所示,随机丢失的表现为57.3%mAP,略好于基线。我们比较的另一个丢弃策略是我们在训练ASDN时应用的类似策略(图3)。我们详细列举了不同种类的遮挡,并在每次迭代中选择最好的遮挡进行训练。表现为57.7%的mAP(Ours(hard dropout)),略好于随机丢弃。
我们发现穷举策略只能探索非常有限的遮挡策略空间,我们使用预先训练的ASDN网络来代替它。然而,当我们固定ASDN的参数时,我们发现性能是57.5%的mAP(Ours(fixed ASDN)),这不如穷尽的策略。原因是固定的ASDN没有收到更新Fast-RCNN的任何反馈,而详尽的搜索得到了反馈。如果我们一起共同学习ASDN和Fast-RCNN,我们可以获得58.5%的mAP,与没有丢弃策略的基线相比,mAP提高1.5%。这个证据表明,ASDN和Fast-RCNN的共同学习是有所不同的。
ASTN分析。我们将对抗空间变换网络与目标候选区域的随机抖动进行了比较。增强包括对Fast-RCNN进行训练的尺寸的随机变化,纵坐标和旋转。使用AlexNet,使用随机抖动的性能为57.3%mAP,而ASTN结果为58.1%。使用VGG16,随机抖动有68.6%mAP而ASTN有69.9%mAP。对于这两种架构,ASTN的模型比随机抖动更好。 简单的阅读OHEM 论文代码:https://github.com/abhi2610/ohem
三、小目标检测
小目标有两种定义方式,一种是相对尺寸大小,如目标尺寸的长宽是原图像尺寸的0.1,即可认为是小目标,另外一种是绝对尺寸的定义,即尺寸小于32*32像素的目标即可认为是小目标。 小目标检测在深度学习卷积神经网络模型中一直是一个难题。早期的目标检测框架大多数是针对通用的目标来进行检测,如经典的单阶段方法yolo和ssd,两阶段方法faster-rcnn等,这些方法主要是针对通用目标数据集来设计的解决方案,因此对于图像中的小目标来说,检测效果不是很理想。 为了解决小目标问题提出的方法有:
图像的缩放。也是最琐碎的一个方向——是在检测前对图像进行缩放。但是,由于大图像变得太大,无法装入GPU进行训练,因此单纯的升级并不有效。ao等[2017]首先下采样图像,然后利用强化学习训练基于注意力的模型,动态搜索图像中感兴趣的区域。然后对选定的区域进行高分辨率的研究,并可用于预测较小的目标。这避免了对图像中每个像素进行同等关注分析的需要,节省了一些计算成本。一些论文[Dai等,2016b,2017年,Singh和Davis, 2018年]在目标检测上下文中训练时使用图像金字塔,而[Ren et al., 2017]在测试时使用。
浅网络。小物体更容易被接受场较小的探测器预测。较深的网络具有较大的接受域,容易丢失关于较粗层中较小对象的一些信息。Sommer等[2017b]提出了一种非常浅的网络,只有四个卷积层和三个完全连接的层,用于检测航空图像中的目标。当期望的实例类型很小时,这种类型的检测器非常有用。但是,如果预期的实例具有不同的大小,则效果更好 上下文信息。利用围绕小对象实例的上下文。Gidaris和Komodakis [2015], Zhu等[2015b]使用上下文来提高性能,Chen等[2016a]则专门使用上下文来提高小对象的性能。他们使用上下文补丁对R-CNN进行了扩展,与区域建议网络生成的建议补丁并行。Zagoruyko等人[2016]将他们的方法与深度掩模对象建议相结合,使信息通过多条路径流动。
超分辨率。还有针对小目标的图像增强等。最典型的是利用生成对抗性网络选择性地提高小目标的分辨率。 它的生成器学会了将小对象的不佳表示增强为超分辨对象,这些超分辨对象与真实的大对象非常相似,足以欺骗竞争的鉴别器。 近两年提出了利用多层特征图的方法(特征金字塔、RNN思想、逐层预测),对小目标检测的效果产生了显著的提升。 现阶段主流算法有: 图像金字塔:较早提出对训练图片上采样出多尺度的图像金字塔。通过上采样能够加强小目标的细粒度特征,在理论上能够优化小目标检测的定位和识别效果。但基于图像金字塔训练卷积神经网络模型对计算机算力和内存都有非常高的要求。计算机硬件发展至今也难有胜任。故该方法在实际应用中极少。 逐层预测:该方法对于卷积神经网络的每层特征图输出进行一次预测,最后综合考量得出结果。同样,该方法也需要极高的硬件性能。 特征金字塔:参考多尺度特征图的特征信息,同时兼顾了较强的语义特征和位置特征。该方法的优势在于,多尺度特征图是卷积神经网络中固有的过渡模块,堆叠多尺度特征图对于算法复杂度的增加微乎其微。
RNN思想:参考了RNN算法中的门限机制、长短期记忆等,同时记录多层次的特征信息(注:和特征金字塔有本质区别)。但RNN固有的缺陷是训练速度较慢(部分操作无法矩阵化)
四:Q&A
问:我觉得博客中有些地方说得不对,我谈下我的个人理解:对正负样本来说,可以理解成是从原始图片中进行截图获得的。并不需要单独去造什么负样本。—原始图片中会截出很多图片,也就是所谓的锚框。然后将锚框截图出来,这些截图会与GT(也就是标注框的区域的图片)计算IOU,IOU大于0.7的,视为正样本,IOU小于0.3的视为负样本,介于两个阈值之间的图片就被丢弃。对IOU小于0.3的截图而言,由于IOU过小,则会被视为并不包含目标物体(即使边角落处有,也是被忽视的)。 因此,我们正常进行标注,提供完整的xml和图片即可。模型在训练过程中,会自行挑选相应数量的正负样本,而不必人为去构造。 如果我理解有误,还请大佬指点下~~
答:直接拿原本的数据集可能会存在误识别的场景中的负样本无法学习到。拿人脸识别来说,在一个动漫的测试样本中发生误识别时,是很难从原先数据集中学习到负样本的,即很难找到有人脸和动漫脸都存在的样本,所以增加负样本训练是降低误识别必要的
问:我觉得这边博主这边说的“负样本”指的是(以行人检测为例,图中原本没有任何人,但是拿训练好的模型去测试,检测结果中存在预测边界框)。对于这种误检测应该采取什么样的处理方式? 博主在上面也提到过直接拿这种图片来训练时,损失为0。主要是因为根据@lmw0320提到的正负样本的定义上。因为图中并不存在着gt boxes。因此这边所有的图都被当成ignore的样本来看待。直接训练根本没有办法处理当前的这个问题。
答:说的没错
问:“正负样本的比例最好为1:1到1:2左右”博主,请教一下,对于一个目标检测模型来说。正样本:负样本中的正样本数目,是所有类别的数据总量还是单个类别的数据量?
答:无
问:我一直没搞明白,对于目标检测算法,最终模型误检率高算是欠拟合还是过拟合?
答:都有看LOSS
答:都有
参考: 目标检测(降低误检测率及小目标检测系列笔记)_Z.w.j的博客-CSDN博客
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/182403.html原文链接:https://javaforall.cn