51c~目标检测~合集1
我自己的原文哦~ https://blog.51cto.com/whaosoft/12371248
#目标检测x1
又一个发现 都不知道是第几了 是一个高效的目标检测 动态候选较大程度提升检测精度
目标检测是一项基本的计算机视觉任务,用于对给定图像中的目标进行定位和分类。
论文地址:https://arxiv.org/pdf/2207.05252.pdf
大多数最先进的检测方法利用固定数量的提议作为候选对象的中间表示,这在推理过程中无法适应不同的计算约束。
在今天分享中,研究者提出了一种简单而有效的方法,该方法通过生成用于目标检测的动态提议来适应不同的计算资源。首先设计一个模块来制作一个基于查询的模型,以便能够用不同数量的提议进行推理。此外,研究者将其扩展到动态模型以根据输入图像选择候选的数量,大大降低了计算成本。新提出的方法在包括两阶段和基于查询的模型在内的各种检测模型中实现了显着的加速,同时获得了相似甚至更好的准确度。
目标检测是一项基本但具有挑战性的计算机视觉任务。给定输入图像,算法旨在同时对图像中的目标进行定位和分类。为了实现良好的目标检测性能,两阶段方法首先生成固定数量的粗略提议,然后对其进行细化以输出细粒度预测。作为成功的双阶段方法之一,R-CNN系列利用区域候选网络(RPN)粗略定位目标,然后提取感兴趣区域特征以输出精细预测。为了简化目标检测的过程,提出了基于查询的方法来移除手动设计的Anchor框。
其中,DETR是一项开创性的工作,将目标检测视为具有多阶段变换器和学习对象查询的直接集合预测问题。Sparse R-CNN设计了一个基于R-CNN检测器的基于查询的集合预测框架。通过用固定数量的可学习候选替换手工制作的候选,Sparse R-CNN有效地减少了候选的数量并避免了多对一的标签分配。
研究者制定了一种训练策略,以促进单个模型根据硬件约束自适应地切换候选的数量。实证研究表明,新提出的模型在相同数量的候选下实现了与单独训练的模型相似的性能。此外,研究者还设计了一个网络模块,根据输入图像的复杂度动态选择proposals的数量,有效降低了计算成本。
如上图,与提出的动态候选相结合,四种所示检测方法的推理速度大幅提高,同时保持了竞争性能。 推理速度是使用单个TITAN RTX GPU测量的。
研究者提出的方法的关键思想是用当前目标检测方法中的动态大小替换固定数量的候选。新提出的模型不是使用固定候选,而是根据输入图像的内容或当前的计算资源选择不同数量的候选,如下图所示。
新提出的方法可以很容易地插入大多数两阶段和基于查询的检测方法。在接下来的部分中,首先回顾了当前带有候选的目标检测方法,并介绍了一种带有可切换候选的训练策略,以使新提出的模型在推理过程中适应不同的配置。然后,将可切换候选扩展到动态候选,以便可以根据输入图像自适应地调整候选编号。最后,引入了一种就地蒸馏策略,在每次训练迭代中将模型中的知识从具有更多候选的网络转移到具有较少候选的网络,这显着提高了新模型的整体性能。
Dynamic Proposa
可切换候选有助于在不同数量的候选下执行两阶段或基于查询的检测模型。在这种情况下,建议的数量是根据外部资源而不是图像的内容来选择的。为了将proposal的数量和计算成本与图像的内容联系起来,研究者使用图像中的物体数量作为指导来生成proposa的动态数量。
在训练过程中,估计图像中的物体数量,记为n~。然后用定义的确定性函数 δ(~n) 替换原始变量δ:
因此δ随着预测目标数量的上限为1线性增长。给定新的动态候选数Nd:
在基于查询的模型中,动态候选特征qd0和框bd0是从原始q0和b0中切片的:
在两阶段模型中,目标候选是从原始候选中采样通过RPN使用下面定义的比率生成的的:
在MS COCO验证集上单独使用多种配置训练的原始方法与使用可切换候选联合训练的原始方法之间的比较。
Cityscapes val上目标检测和实例分割的基线模型进行比较。“DP”表示结合动态候选的模型。如下表:
具有动态候选的目标检测及其相应的估计目标数量和候选数量。第一列显示来自MS-COCO的图像,第二列显示来自Cityscapes的图像。
#优化
这里总结自己在图像预处理调参、模型训练调参等方面中的技巧,并提醒读者要多注意数据的分布和呈现的状态。
对卷积网络来说,所学习的就是数据集的数据分布,你的卷积核参数最后形成的也是对数据集中特征分布的认知。
写这篇文章就是因为up主的邀请,然后分享一下自己工作时候总结的一些经验和技巧,不一定适用别的网络,有的还可能会有反作用,所以也就是给大家提供一个思路,欢迎拍砖吧,因为都是公司数据,分享试验结果也比较麻烦,所以大家看个思路就好。
1、预处理技巧分享
图像预处理部分调参的主要目的是对输入数据进行增强,使得网络模型在训练的过程中能更专注于目标特征部分的学习。常用的方式是图像的随机旋转、裁剪以及翻转等方式,这些方式的预处理其本质其实是为了让你的数据集更丰富,让网络能够学习到更多的分布情况,这个网上已经有很多博客了,笔者就不赘述了;另一种调整的trick是在图像上叠加信息,例如在输入数据上增加高斯噪声,椒盐噪声,从而提升网络对有干扰和成像较差情况下的目标检测能力。本文将对图像上叠加信息的调参技巧进行一定的扩展讲解。
1、为什么在原始图像上叠加信息会管用,不会破坏原有的图像信息么?
在图像上叠加信息分成两类,一类是叠加噪声,这种操作的目的是为了让网络能够适应图像质量不佳情况下的图像检测任务,在板端实测的结果,这种叠加噪声的方式也可以一定程度提高网络对输入图像中待检测目标的仿射变换的适应能力。笔者通过在输入图像上叠加一定量的高斯噪声,在Hi3516CV500上完成基于yolov3-tiny的车牌检测任务时,提高了0.5%的精度。
另一类信息的叠加是对尝试对图像上某一特定特征进行增强,该增强的目的是突出该方面的图像特征,使得网络能够首先注意到该种特征并更专注于此类特征的学习,因为这种方式只是对图像中的指定特征或位置有变动,并不会整体上对图像的结构有巨大的改变,所以并不会破坏图像的信息可读性。例如:利用canny算子对图像中的边缘特征进行增强。
2、上面说的两种调参技巧是怎么想出来的?
我们都知道,网络学习的是数据中的参数分布,何凯明大神也在retinanet的论文里提到过,数据的不平衡是影响检测网络性能的主要因素,而focal loss的提出就是让网络在学习时更专注于漏检和误分的样本。那么我们接着这个思路想,如何使得网络更专注于目标区,从而获得尽量多的价值更高的误捡和漏检样本呢?花朵吸引蜜蜂靠的是自己的香味和更鲜艳的外表,所以我们也要让目标区域更“显眼”,而平时在训练检测网络时,发现对数据集进行标注时,anchor base类算法,目标标注框比实际的物体紧缩框大大概几个像素时得到的检测结果统计精度和定位框的稳定性都会好,那么我们是不是可以认为,对anchor base的检测网络来说,目标物体的边缘也是很重要的,所以就想到了通过canny算子增强边缘的方式来增强训练数据。
3、如何在实际的网络训练中应用以上的技巧?
实际使用过程如下:
1)通过对输入数据的手动查验或自动化统计,确定较好的canny阈值
2)利用阈值对训练样本中10-20个batch的数据进行canny边缘增强。
3)增强方式为:原图转灰度提取到的canny边缘所对应的原图像素位置进行对比度增强或直接涂黑。加深程度可以由自定义的超参数alpha来指定。
4)用这10-20个batch的数据进行几个epoch的训练后再换成普通数据进行训练。
2、模型训练参数调整
讲了预训练时候的数据增强,接下来是模型训练参数部分。其实这部分网上讲的trick很多了,大家平时注意搜集一下或者github上找一找,就有很多人的练手的仓库可以跟着学。我也就不多讲了,因为我也不敢说学全了。我讲讲我自己实际跑模型时候的一些想法。
1、BFEnet特征擦除网络
这个网络是reid方向的,先讲这个是因为,这个特征擦除和上面讲到的噪声本质上有相似的地方,都是通过在训练时遮蔽一部分特征值,来让网络习惯一定量的噪声干扰,从而增强性能。这个技巧可以用在应对有遮挡的场景下的模型。
2、anchor的调整
在yolo的代码里大家肯定都看了,作者是根据你给的数据集里面,标定的目标的长和宽进行k-means的聚类,然后确定在当前这个数据集上的anchor的。我这里的经验就是,我发现有人问过我为啥我只训练一类的检测,然后重新计算的anchor6个或者9个anchor尺寸差的都不大,但是在实际检测的时候,却检测不到东西。我的结论是:对anchor的设计应该是基于模型作者默认的anchor进行微调而不是完全的重新计算。
原因:大家都知道,yolov3来说,输出是三个特征图,分别对应小目标,中目标和大目标。比如我们要检测的目标在图像中占比我们人眼感觉应该是比较大的,然后我们统计的框也都是比较大的尺寸,但是在实际训练的时候,并不是说大目标就一定由yolov3的最初设计的大目标输出层输出的。很可能就是由中间目标层输出的,而因为anchor的设计过大,导致训练的网络不收敛的有之,明明收敛了,却检测不到目标的情况也有之。
解决办法:在设计anchor的时候,首先统计目标框的分布,然后进行聚类,聚类后替换或修改原有的9个anchor中和你计算的anchor相近的几个原有的anchor值。然后再训练,如果框还是不够紧缩,再对某几个框进行精调就可以了,核心思路就是:anchor的分布也要满足对全集的稀疏覆盖而不仅仅是你的当前数据集。
3、后处理的优化
后处理的优化部分严格来说不算是网络训练的trick了,应该是部署的trick,比如海思的NPU部署的时候,会限制比较大的pool核,所以最好训练的时候就把大的pooling切换为几个小的连续pooling,实测虽然理念上两者应该是差不多的,但是实际上还是差了0.3%的精度。(指的是直接多层的pooling转换到板子和训练时是一个大的pooling,到转换时候再改结构成几个小的pooling)
还有一个就是nms部分,这部分也有同学问过我说因为我的数据集有遮挡,可能两个离的比较近的,nms就把有遮挡的那个小目标去掉了。这部分分享一个小技巧就是,你在算nms的时候,也关注一下两个框的中心点距离,可以设置中心点距离超过多少的两个框,不做nms。这样就能避免nms的一部分武断删除检测结果bbox。
4、大模型训练时的一个训练技巧
有一位同学问过我,就是为啥同样的模型,用比较少的数据训练的时候很快到了97%的MAP,但是换300w的大数据集的训练以后,卡在93%上不去了。这里面有一个技巧叫warm up,也就是说在大数据下训练模型的时候,可以先从大数据集上取一部分数据训练模型,然后以这个训练的模型为预训练模型,在大数据集上,增大batch_size再进行训练,至少没卡在93%这个问题上了。
5、学习率手动修正策略
我们训练的时候,一般都会设置学习率的衰减,有很多的方式,按已迭代步长的,按当前损失值的,按训练集当前损失值和测试集计算的损失值的gap差值做修正项的。我这里提到的技巧就是比如以步长调整学习率为例,什么时候可以靠自动化的修正学习率,什么时候要手动调整一下。
我们在训练模型的时候,一般都会关注损失函数变化曲线图,在曲线图中,数据集的稀疏程度能通过损失曲线的震荡情况有一定的反映,如果有个别的跳点,多为数据集中的坏数据(标记错误数据),当我们的损失图呈现为震荡--阶跃--在另一个损失值附近震荡时,就要注意了,此时多半是因为你的数据集在做打乱的时候数据并没有打的很散,可以在这个位置先停止训练并记录当前状态,再降低学习率,继续训练,等训练数据再次开始恢复之前的震荡位置时,再恢复学习率训练。
这样操作的原因是为了避免在参数中引入过大的噪声,噪声分两种,一种就是错误的数据,比如背景啊,像目标但是不是目标的东西,还有就是多类别训练的时候,对每个类别来说,其余类别也算是噪声的一种。所以采用要么把数据集弄好(这个很难,我也没看过谁的文章里真的能说清把训练集弄好是啥样的),要么加大batch,要么就训练时候注意。
3、总结
模型的调参训练技巧其实说白了就是怎么让模型得到的是数据全集的稀疏分布,且和别的类别有比较好的区分,也就是类内差小类间差则尽量大。以这个为核心,告诉模型应该关注什么,少关注什么,既然是数据的科学,多关注数据的分布和呈现的状态,祝大家在训练的时候都得到自己满意的结果。
#Box Size置信度偏差会损害目标检测器
检测器的置信度预测在目标大小和位置方面存在偏差,但目前尚不清楚这种偏差与受影响的目标检测器的性能有何关系。
无数应用依赖于目标检测器的可靠置信度估计的准确预测。然而,众所周知,包括目标检测器在内的神经网络会产生错误校准的置信估计。最近的工作甚至表明,检测器的置信度预测在目标大小和位置方面存在偏差,但目前尚不清楚这种偏差与受影响的目标检测器的性能有何关系。
研究者正式证明条件置信偏差(conditional confidence bias)正在损害目标检测器的预期性能,并凭经验验证这些发现。具体来说,研究者们演示了如何修改直方图分箱校准,不仅可以避免性能受损,还可以通过条件置信校准来提高性能。
研究者进一步发现,在检测器的训练数据上生成的检测器中也存在置信偏差,利用这些偏差在不使用额外数据的情况下执行提出的去偏差。此外,Test Time Augmentation会放大这种偏差,从而从我们的校准方法中获得更大的性能提升。最后,研究者在一组不同的目标检测架构上验证了他们的发现,并在没有额外数据或训练的情况下显示了高达0.6 mAP和0.8 mAP50的改进。
Accurate probability estimates对于自动化决策过程至关重要。它们对于准确可靠的性能以及正确评估风险至关重要。对于目标检测器来说尤其如此,它们经常部署在自动驾驶、医学成像和安全应用等独特的关键领域,这些领域可能危及人的生命。尽管存在这些高风险,目标检测器的置信度校准受到的关注相对较少。目标检测器设计中的大部分注意力都集中在追求性能基准上的最新结果,而忽略了其预测置信度方面的问题。 此外,最近已经证明目标检测器在其位置回归预测方面也容易受到条件置信偏差的影响,但目前尚不清楚这种偏差与受影响目标检测器的性能有何关系?
为了强调置信校准的重要性,研究者表明条件置信偏差正在损害目标检测性能。该现象的简化说明如下图所示。
新方法分析
Evaluating Object Detectors
Confidence Calibration
置信度校准背后的想法是,每个预测的ci应该等于经验目标检测器的TP预测概率P(τ i=1| d=di)。从这里开始,我们将其简称为Pi。对于置信度校准,将目标检测器视为一个随机过程。预测di的标签现在由随机变量Ti∼Bernoulli(Pi)表示,从中抽取tIoU=0.50的τi作为样本。Pi也可以看作是目标检测器对于具有相同置信度ci的一组检测的精度;将Pi称为“successful”或TP检测的概率P(τ i=1| d=di)以避免与上等式中定义的度量混淆。
Bias in Confidence of Object Detector
研究者假设条件置信偏差正在损害目标检测器的性能。 如第一张图,基于具有不同校准曲线的两组检测的夸大示例来形象化这个想法。 每个组只有一个各自的置信值的检测,在这个例子中很明显,置信阈值为0.55的检测器对于未校准检测(0,1)的精度为50%;如果检测器被完美校准 (2,3),精度为70%。 在精确召回曲线中可以观察到相关的改进。 该曲线下的面积与AP指标密切相关。 简单示例和假设表明,目标检测器相对于边界框大小和位置的置信估计偏差正在损害检测器的性能。
接下来都是算式证明
Maximizing Average Precisio
为了证明提出的假设,即置信偏差正在损害目标检测器的性能,我们看一下AP与P的关系以及如何在一组检测D中最大化它。目标检测器可以被视为一个随机过程 ,所以我们需要分析预期的AP:
Confidence Calibration
不同边界框大小的置信度校准的变化降低了检测器的预期性能。现在已经证明了这个假设,研究者希望在证明的基础上通过校正校准曲线之间的变化来提高检测器的性能,看看它是否会提高性能指标。
如果找到消除条件偏差的检测置信度映射,则消除了变化,从而产生了相等的校准曲线。这可以通过将置信度映射为每个边界框大小的成功概率来实现。当然,概率通常是未知的,但置信度校准正好解决了找到将置信度分数映射到他们的经验成功概率的函数的问题。
根据以上的推理,条件置信校准应该减少目标检测器的框大小置信偏差。减少这种偏差应该会增加检测器的AP。我们尝试使用公开可用的目标检测器CenterNet来验证这一点,它带有Hourglass的主干网络,并在COCO上进行了训练。我们以60:40的比例分割2017 COCO验证集,在第一个分割上进行校准,并在较小的第二个分割上评估校准检测。我们对80个类别中的每一个类别进行类别校准以考虑不同类别的变化,然后将每个类别的检测分为三个大小相同的边界框大小的子组。每个子组都使用具有7个置信区间的直方图分箱进行校准。校准检测的性能显着差于未校准检测的,35.7 mAP和40.1mAP。这个结果与我们最初的推理和形式证明相矛盾,发生了什么?
Modifying Histogram Binning
研究者仔细研究histogram binning,以了解为什么它会大大降低测试检测器的性能。发现它违反了我们先前的一些假设,我们修改了标准直方图分箱校准以实际验证我们的原始假设,即我们可以使用校准来提高预测性能。为此,我们在直方图分箱中加入以下假设:
第一个假设是校准提高了我们根据预测成为TP的概率对预测进行排序的能力。直方图合并将置信范围映射到单个估计的精度值,丢弃细粒度的置信差异,如下图:
由于我们已经根据它们的大小将检测分为子组,我们可以假设检测器在这些子组中产生有意义的置信度排序:毕竟,这是它的训练目标。由于我们希望保持每个子组内的排序,我们在直方图bin的中心之间添加linear splines。
我们还将对splines的supports设置为每个bin中检测的平均置信度,以最大限度地减少每个bin内不均匀分布的置信度造成的错误。在上图右中可以看到supports处减少的方差以及所有修改。我们像以前一样在同一个目标检测器上测试每个修改和最终修改的校准函数。结果见之前的表格验证个别修改和我们最初的假设,即框大小置信偏差降低了目标检测器的性能,而我们的校准可以减少这种偏差并提高性能。
还有较多的证明推理,可以在论文中继续详读了解:
https://arxiv.org/pdf/2112.01901.pdf
实验
扩展优化指标的 mAP 性能变化
#目标检测新方式x1
目标检测模型在定位和分类训练期间显示目标时表现良好,然而,由于创建和注释检测数据集的难度和成本,训练过的模型检测到数量有限的目标类型,未知目标被视为背景内容。这阻碍了传统检测器在现实应用中的采用,如大规模物体匹配、visual grounding、视觉关系预测、障碍检测(确定物体的存在和位置比找到特定类型更重要)等。
目标检测模型在定位和分类训练期间显示目标时表现良好,然而,由于创建和注释检测数据集的难度和成本,训练过的模型检测到数量有限的目标类型,未知目标被视为背景内容。这阻碍了传统检测器在现实应用中的采用,如大规模物体匹配、visual grounding、视觉关系预测、障碍检测(确定物体的存在和位置比找到特定类型更重要)等。
有研究者提出类不可知目标检测作为一个新问题,专注于检测对象的对象类。具体地说,其目标是预测图像中所有对象的边界框,而不是预测它们的对象类。预测的框可以被另一个系统使用,以执行特定于应用程序的分类、检索等。
提出了针对类不可知检测器的基准测试的训练和评估协议,以推进该领域的未来研究。最后,研究者提出了:(1)基线方法和(2)一个新的用于类无关检测的对抗性学习框架,它迫使模型从用于预测的特征中排除特定于类的信息。实验结果表明,对抗性学习方法提高了类不可知性的检测效率。
会有同学会问“目标检测中bbox回归中class-agnostic和class-specific的区别在哪?”。今天我们简单说一下,然后开始今天主框架的分析。
- class-specific 方式:很多地方也称作class-aware的检测,是早期Faster RCNN等众多算法采用的方式。它利用每一个RoI特征回归出所有类别的bbox坐标,最后根据classification 结果索引到对应类别的box输出。这种方式对于ms coco有80类前景的数据集来说,并不算效率高的做法。
- class-agnostic 方式:只回归2类bounding box,即前景和背景,结合每个box在classification 网络中对应着所有类别的得分,以及检测阈值条件,就可以得到图片中所有类别的检测结果。当然,这种方式最终不同类别的检测结果,可能包含同一个前景框,但实际对精度的影响不算很大,最重要的是大幅减少了bbox回归参数量。具体细节,自己参考目前一些开源算法源码会理解的更好。
Class-agnostic目标检测器使用object proposal methods (OPMs), conventional class-aware detectors和提出的adversarially trained class-agnostic detectors。如下图:
绿色和紫红色分别是真值和检测结果。
新框架 General Framework
传统的类感知检测侧重于检测“感兴趣的对象”,这本质上要求模型能够区分封闭已知集合中的对象类型。直观地说,模型通过编码区分对象类型的特征来实现这一点。然而,为了使类不可知的检测和模型能够检测到以前看不见的对象类型,检测器应该编码能够更有效地区分对象与背景内容、单个对象与图像中的其他对象的特征,而不区分对象类型。
训练传统的目标检测器的二元分类任务以及边界框回归不足以确保模型关注类无关特征,更重要的是,忽略类型区分特征,以便更好地推广到看不见的目标类型。为了克服这个问题,研究者建议以一种对抗性的方式训练类不可知的目标检测器,以便模型因编码包含目标类型信息的编码特征而受到惩罚。
研究者提议用对抗性鉴别器分支来增强类不可知的检测器,这些分支试图从检测网络上游输出的特征中分类对象类型(在训练数据中注释),如果模型训练成功,则对其进行惩罚。模型以交替的方式训练,这样当模型的其余部分更新时,鉴别器被冻结,反之亦然。在更新鉴别器时,研究者使用标准的分类交叉熵损失的目标类型作为预测目标。另一方面,在训练模型的其余部分时,最小化(a)目标与否分类的交叉熵损失,(b)边界框回归的平滑L1损失,以及(c)鉴别器预测的负熵。这种熵最大化迫使检测模型的上游部分从其输出的特征中排除目标类型信息。对于模型的每次更新,鉴别器被更新五次,在整个目标中使用乘子α(调整{0.1,1})对负熵进行加权。上图总结了完整的框架。
实验
#正负样本区分策略和平衡策略总结
从正负样本区分和正负样本平衡策略进行分析,大体可以分为正负样本定义、正负样本采样和平衡loss设计三个方面,主要是网络预测输出和loss核心设计即仅仅涉及网络的head部分。
本文抛弃网络具体结构,仅仅从正负样本区分和正负样本平衡策略进行分析,大体可以分为正负样本定义、正负样本采样和平衡loss设计三个方面,主要是网络预测输出和loss核心设计即仅仅涉及网络的head部分。所有涉及到的代码均以mmdetection为主。本文第一部分,主要包括faster rcnn、libra rcnn、retinanet、ssd和yolo一共5篇文章。第二部分包括anchor-free的平衡策略,以及最新改进算法。第三部分重点分析下anchor-free和anchor-base混合学习的Guided Anchoring以及yolo-ASFF,包括思路和代码。
1 anchor-base
1.1 two-stage
1.1.1 faster rcnn
论文名称:Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks
(1) head结构
faster rcnn包括两个head:rpn head和rcnn head。其结构如下:
rpn head的输出是包括分类和回归,分类是二分类,只区分前景和背景;回归是仅仅对于前景样本(正样本)进行基于anchor的变换回归。rpn head的目的是提取roi,然后输入到rcnn head部分进行refine。rcnn head的输出是包括分类和回归,分类输出是类别数+1(1是考虑背景),回归是仅仅对于前景样本不考虑分类类别进行基于roi的变换回归,rcnn head的目的是对rpn提取的roi特征进行refine,输出精准bbox。
(2) 正负样本定义
rpn和rcnn的正负样本定义都是基于MaxIoUAssigner,只不过定义阈值不一样而已。rpn的assigner:
rcnn的assigner:
下面对MaxIoUAssigner进行详细分析。首先分析原理,然后分析细节。正负样本定义非常关键。MaxIoUAssigner的操作包括4个步骤:
- 首先初始化时候假设每个anchor的mask都是-1,表示都是忽略anchor
- 将每个anchor和所有gt的iou的最大Iou小于neg_iou_thr的anchor的mask设置为0,表示是负样本(背景样本)
- 对于每个anchor,计算其和所有gt的iou,选取最大的iou对应的gt位置,如果其最大iou大于等于pos_iou_thr,则设置该anchor的mask设置为1,表示该anchor负责预测该gt bbox,是高质量anchor
- 3的设置可能会出现某些gt没有分配到对应的anchor(由于iou低于pos_iou_thr),故下一步对于每个gt还需要找出和最大iou的anchor位置,如果其iou大于min_pos_iou,将该anchor的mask设置为1,表示该anchor负责预测对应的gt。通过本步骤,可以最大程度保证每个gt都有anchor负责预测,如果还是小于min_pos_iou,那就没办法了,只能当做忽略样本了。从这一步可以看出,3和4有部分anchor重复分配了,即当某个gt和anchor的最大iou大于等于pos_iou_thr,那肯定大于min_pos_iou,此时3和4步骤分配的同一个anchor。
从上面4步分析,可以发现每个gt可能和多个anchor进行匹配,每个anchor不可能存在和多个gt匹配的场景。在第4步中,每个gt最多只会和某一个anchor匹配,但是实际操作时候为了多增加一些正样本,通过参数gt_max_assign_all可以实现某个gt和多个anchor匹配场景。通常第4步引入的都是低质量anchor,网络训练有时候还会带来噪声,可能还会起反作用。
简单总结来说就是:如果anchor和gt的iou低于neg_iou_thr的,那就是负样本,其应该包括大量数目;如果某个anchor和其中一个gt的最大iou大于pos_iou_thr,那么该anchor就负责对应的gt;如果某个gt和所有anchor的iou中最大的iou会小于pos_iou_thr,但是大于min_pos_iou,则依然将该anchor负责对应的gt;其余的anchor全部当做忽略区域,不计算梯度。该最大分配策略,可以尽最大程度的保证每个gt都有合适的高质量anchor进行负责预测,
下面结合代码进行分析:主要就是assign_wrt_overlaps函数,核心操作和注释如下:
通过代码可以发现,当设置self.gt_max_assign_all=True时候是可能出现第4步的某个gt和多个anchor匹配场景,默认参数就是True。
由于rcnn head预测值是rpn head的refine,故rcnn head面对的anchor(其实就是rpn输出的roi)和gt的iou会高于rpn head部分,anchor质量更高,故min_pos_iou阈值设置的比较高,由于pos_iou_thr和neg_iou_thr设置都是0.5,那么忽略区域那就是没有了,因为rcnn head面对的都是高质量样本,不应该还存在忽略区域。
(3) 正负样本采样
步骤2可以区分正负和忽略样本,但是依然存在大量的正负样本不平衡问题,解决办法可以通过正负样本采样或者loss上面一定程度解决,faster rcnn默认是需要进行正负样本采样的。rpn head和rcnn head的采样器都比较简单,就是随机采样,阈值不一样而已。rpn head采样器:
rcnn head采样器:
num表示采样后样本总数,包括正负和忽略样本,pos_fraction表示其中的正样本比例。add_gt_as_proposals是为了放在正样本太少而加入的,可以保证前期收敛更快、更稳定,属于技巧。neg_pos_ub表示正负样本比例,用于确定负样本采样个数上界,例如我打算采样1000个样本,正样本打算采样500个,但是可能实际正样本才200个,那么正样本实际上只能采样200个,如果设置neg_pos_ub=-1,那么就会对负样本采样800个,用于凑足1000个,但是如果设置为neg_pos_ub比例,例如1.5,那么负样本最多采样200x1.5=300个,最终返回的样本实际上不够1000个。默认情况neg_pos_ub=-1。由于rcnn head的输入是rpn head的输出,在网络训练前期,rpn无法输出大量高质量样本,故为了平衡和稳定rcnn训练过程,通常会对rcnn head部分添加gt作为proposal。其代码非常简单:
对正负样本单独进行随机采样就行,如果不够就全部保留。
由于原始faster rcnn采用的loss是ce和SmoothL1Loss,不存在loss层面解决正负样本不平衡问题,故不需要分析loss。
1.1.2 libra rcnn
论文名称:Libra R-CNN: Towards Balanced Learning for Object Detection
libra主要是分析训练过程中的不平衡问题,提出了对应的解决方案。由于libra rcnn的head部分和正负样本定义没有修改,故不再分析,仅仅分析正负样本采样和平衡loss设计部分。
(1) 正负样本采样
注意libra rcnn的正负样本采样规则修改仅仅是对于rcnn而言,对于rpn head没有任何修改,依然是随机采样器。原因是作者的主要目的是为了涨点mAP,作者认为rpn涨几个点对最终bbox 预测map没有多大帮助,因为主要是靠rcnn部分进行回归预测才能得到比较好的mAP。其参数如下:
主要看IoUBalancedNegSampler部分即可。仅仅作用于负样本(iou=0~0.5之间)。作者认为样本级别的随机采样会带来样本不平衡,由于负样本本身iou的不平衡,当采用随机采样后,会出现难负(iou 0.5附近)和易负(iou接近0)样本不平衡采样,导致后面性能不好。作者发现了如果是随机采样的话,随机采样到的样本超过70%都是在IoU在0到0.05之间的,都是易学习负样本,作者觉得是不科学的,而实际统计得到的事实是60%的hard negative都落在IoU大于0.05的地方,但是随机采样只提供了30%,实在是太少了。最常用的解决难易样本不平衡问题的解决办法就是ohem,基于Loss排序来采样难负样本,但是作者分析,(1) 这种方法对噪音数据会比较敏感,因为错误样本loss高;(2) 参数比较难调。所以作者提出了IoU-balanced Sampling,如下所示:
可以看出,随机采样效果最不好,而iou balanced sampling操作会尽量保证各个iou区间内都会采样到。由于该操作比较简单,就不贴论文公式了。核心操作是对负样本按照iou划分k个区间,每个区间再进行随机采样,保证易学习负样本和难负样本比例尽量平衡,实验表明对K不敏感,作者设置的是3。具体做法是对所有负样本计算和gt的iou,并且划分K个区间后,在每个区间内均匀采样就可以了。假设分成三个区间,我想总共取9个,第一个区间有20个候选框,第二个区间有10个,第三个区间有5个,那这三个区间的采样概率就是9/(3x20),9/(3x10),9/(3x5),这样的概率就能在三个区间分别都取3个,因为区间内候选框多,它被选中的概率小,最终体现各个区间都选这么多框。
实际代码做法是:首先按照iou分成k个区间,先尝试在不同区间进行随机采样采相同多数目的样本,如果不够就全部采样;进行一轮后,如果样本数不够,再剩下的样本中均匀随机采样。例如假设总共有1000个候选负样本(区间1:800个,区间2:120个,区间3:80个),分为3个区间,总共想取333个,那么理论上每个区间是111个,首先第一次在不同区间均匀采样,此时区间1可以采样得到111个,区间2也可以得到111个,区间3不够,所以全部保留;然后不够的样本数,在剩下的(800-111)+(120-111)+0个里面随机取31个,最终补齐333个。核心代码如下:
意思是在各个区间内,如果够数目就随机采样,如果不够那就剩下的负样本里面全部采样。
(2) 平衡回归loss
为了突出难样本梯度,需要重新设计梯度函数,作者想到了如下函数:
左边是梯度曲线,右边是loss曲线,可以看出非常巧妙。
1.2 one-stage
1.2.1 focal loss
论文名称:Feature Pyramid Networks for Object Detection
该论文也叫做retinanet,是目前非常主流的FPN目标检测one-stage网络结构,本文主要是提出了一个focal loss来对难易样本进行平衡,属于平衡loss范畴。
(1) 网络结构
由于该网络结构非常流行,故这里仅仅简要说明下,不做具体分析。
图(d)即为retinanet的网络结构。主要特点是:(1) 多尺度预测输出;(2) 采用FPN结构进行多层特征图融合。网络进行多尺度预测,尺度一共是5个,每个尺度共享同一个head结构,但是分类和回归分支是不共享权重的。
为了方便和faster rcnn进行对比,下面再次贴出rpn结构,并解释参数含义。
1. 共同部分
anchor_strides表示对应的特征图下采样次数,由于retinanet是从stage1开始进行多尺度预测,故其stride比rpn大一倍;anchor_ratios表示anchor比例,一般是1:1,1:2和2:1三种;
2. 不同部分
(2) 正负样本定义
retinanet是one-stage算法,其采用的正负样本定义操作是MaxIoUAssigner,阈值定义和rpn不一样,更加严格。如下所示:
min_pos_iou=0,可以保证每个GT一定有对应的anchor负责预测。0.4以下是负样本,0.5以上且是最大Iou的anchor是正样本0.4~0.5之间的anchor是忽略样本。其不需要正负样本采样器,因为其是通过平衡分类loss来解决的。
(3) 平衡分类loss
FocalLoss是本文重点,是用于处理分类分支中大量正负样本不平衡问题,或者说大量难易样本不平衡问题。作者首先也深入分析了OHEM的不足:它通过对loss排序,选出loss最大的example来进行训练,这样就能保证训练的区域都是hard example,这个方法的缺陷,是把所有的easy example(包括easy positive和easy negitive)都去除掉了,造成easy positive example无法进一步提升训练的精度(表现的可能现象是预测出来了,但是bbox不是特别准确),而且复杂度高影响检测效率。故作者提出一个简单且高效的方法:Focal Loss焦点损失函数,用于替代OHEM,功能是一样的,需要强调的是:FL本质上解决的是将大量易学习样本的loss权重降低,但是不丢弃样本,突出难学习样本的loss权重,但是因为大部分易学习样本都是负样本,所以顺便解决了正负样本不平衡问题。其是根据交叉熵改进而来,本质是dynamically scaled cross entropy loss,直接按照loss decay掉那些easy example的权重,这样使训练更加bias到更有意义的样本中去,说通俗点就是一个解决分类问题中类别不平衡、分类难度差异的一个 loss。
上面的公式表示label必须是one-hot形式。只看图示就很好理解了,对于任何一个类别的样本,本质上是希望学习的概率为1,当预测输出接近1时候,该样本loss权重是很低的,当预测的结果越接近0,该样本loss权重就越高。而且相比于原始的CE,这种差距会进一步拉开。由于大量样本都是属于well-classified examples,故这部分样本的loss全部都需要往下拉。其简单思想版本如下:
1.2.2 yolov2 or yolov3
论文名称:YOLOv3: An Incremental Improvement
yolov2和yolov3差不多,主要是网络有差异,不是我们分析的重点,下面以yolov3为例。
(1) head结构
yolov3也是多尺度输出,每个尺度有3个anchor。对于任何一个分支都是输出[anchor数×(x,y,w,h,confidence,class类别数)h',w']。需要注意的是,其和faster rcnn或者ssd不一样,其类别预测是不考虑背景的,所以才多引入了一个confidence的概念,该分支用于区分前景和背景。,所以最复杂的设计就在condidence上面了。
(2) 正负样本定义
yolo系列的正负样本定义比较简单,原则和MaxIoUAssigner(固定anchor和gt值计算)非常类似,但是更加简单粗暴:保证每个gt bbox一定有一个唯一的anchor进行对应,匹配规则就是IOU最大,而没有考虑其他乱七八糟的。具体就是:对于某个ground truth,首先要确定其中心点要落在哪个cell上,然后计算这个cell的每个anchor与ground truth的IOU值,计算IOU值时不考虑坐标,只考虑形状(因为anchor没有坐标xy信息),所以先将anchor与ground truth的中心点都移动到同一位置(原点),然后计算出对应的IOU值,IOU值最大的那个先验框anchor与ground truth匹配,对应的预测框用来预测这个ground truth。这个匹配规则和ssd和faster rcnn相比,简单很多,其没有啥阈值的概念。对于分类分支和bbox回归分支,采用上述MaxIoU分配原则,可以保证每个gt bbox一定有唯一的anchor进行负责预测,而不考虑阈值,即使某些anchor与gt的匹配度不高也负责,而faster rcnn里面的MaxIoUAssigner是可能由于anchor设置不合理导致某个gt没有anchor进行对应,而变成忽略区域的。可以看出这种分配制度会导致正样本比较少。对于confidence分支,其在上述MaxIoU分配原则下,还需要从负样本中划分出额外的忽略区域。因为有些anchor虽然没有和gt有最大iou,但是其iou依然很高,如果作为正样本来对待,由于质量不是很高以及为了和分类、回归分支的正样本定义一致,所以不适合作为正样本,但是如果作为负样本那也不合适,毕竟iou很大,这部分位置的anchor就应该设置为忽略区域,一般忽略iou阈值是0.7即将负样本中的iou大于0.7中的anchor设置为忽略区域(需要特别注意一个细节:此处的iou是每个位置的anchor预测值和所有gt计算iou,而不是固定的anchor和所有gt计算iou,因为此处需要考虑位置信息,faster rcnn系列不需要这么算的原因是faster rcnn是每个位置都会预测xywh,而yolo系列是基于grid网格预测,xy和wh预测是分开来的,所以会更复杂一些)。总结就是:
1.基于max iou分配准则,区分正负样本
2.在负样本范围内,将iou(基于anchor预测值和gt计算)大于忽略阈值的anchor定义为忽略区域,实时改变
3.此时就区分出了正、负和忽略anchor样本,正anchor用于分类、回归分支学习,正负anchor用于confidence分支学习,忽略区域不考虑。
对于yolov3,由于是多尺度预测,故还有一个细节需要注意:首先需要将gt利用 max iou原则分配到不同的预测层上去,然后在每个层上单独计算正负样本和忽略样本,也就是和faster rcnn不一样的地方是yolov3不存在某个gt会分配到多个层进行预测的可能性,而是一定是某一层负责的。但是不同的具体代码实现时候可能会有些许差别。
(3) loss
由于其采用的是普通的bce分类Loss和smooth l1 回归loss,故不再进行分析。
1.2.3 ssd
论文地址:SSD: Single Shot MultiBox Detector
(1) head结构
ssd是最典型的多尺度预测结构,是非常早期的网络。
其ssd300的head结构如下:
可以看出,ssd一共包括6个尺度输出,每个尺度的strides可以从anchor_strides中看出来,basesize_ratio_range表示正方形anchor的min_size和max_size,anchor_ratios表示每个预测层的anchor个数,以及比例。有点绕,下面具体分析。为了方便设置anchor,作者设计了一个公式来生成anchor,具体为:
- 以feature map上每个点的中点为中心(offset=0.5),生成一些列同心的prior box(然后中心点的坐标会乘以step,相当于从feature map位置映射回原图位置)。
- 正方形prior box最小边长为和最大边长为:min_size和
- 根据aspect ratio,会生成2个长方形,长宽为
目的是保存在该比例下,面积不变。以fc7为例,前面知道其min_size=60,max_size=111,由于其需要6种比例,故生成过程是:
不管哪个框架实现,核心思想都是一样,但是可能某些数据的设置不一样。下面以mmdetection为例:
(2) 正负样本定义
ssd采用的正负样本定义器依然是MaxIoUAssigner,但是由于参数设置不一样,故有了不同的解释。
其定义anchor与gt的iou小于0.5的就全部认为是负样本,大于0.5的最大iou样本认为是正样本anchor,同时由于min_pos_iou=0以及gt_max_assign_all=False,可以发现该设置的结果是每个gt可能和多个anchor匹配上,匹配阈值比较低,且每个gt一定会和某个anchor匹配上,不可能存在gt没有anchor匹配的情况,且没有忽略样本。总结下意思就是:
- anchor和所有gt的iou都小于0.5,则认为是负样本
- anchor和某个gt的最大iou大于0.5,则认为是正样本
- gt和所有anchor的最大iou值,如果大于0.0,则认为该最大iou anchor是正样本
- 没有忽略样本
(3) 平衡分类loss
由于正负样本差距较大,如果直接采用ce和smooth l1训练,效果可能不太好,比较样本不平衡严重。故作者的ce loss其实采用了ohem+ce的策略,通过train_cfg.neg_pos_ratio=3来配置负样本是正样本的3倍。
核心就是按照分类loss进行topk,得到3倍的负样本进行反向传播。
2 anchor-free
2.1 fcos
论文名称:FCOS: Fully Convolutional One-Stage Object Detection
FCOS堪称anchor free论文的典范,因为其结构主流,思路简单清晰,效果蛮好,故一直是后续anchor free的基准对比算法。FCOS的核心是将输入图像上的位置作为anchor point的中心点,并且对这些anchor point进行回归。
(1) head结构
fcos的骨架和neck部分是标准的resnet+fpn结构,和retinanet完全相同。如下所示:
我们仅仅考虑head部分。除去center-ness分支,则可以看出和retinanet完全相同。其配置如下:
可以看出一共5个尺度进行预测,每个尺度的stride可以从strides中看出来。由于其是anchor free论文,故少了很多复杂参数。
(2) 正负样本定义
考虑到anchor free预测值和anchor base不一样,故还是需要提前说下网络预测形式。FCOS是全卷积预测模式,对于cls分支,输出是h x w x (class+1),每个空间位置值为1,表示该位置有特定类别的gt bbox,对于回归分支,输出是h x w x 4,其4个值的含义是
每个点回归的4个数代表距离4条边的距离,非常简单易懂。和所有目标检测算法一样,需要提前定义好正负样本,同时由于是多尺度预测输出,还需要首先考虑gt由哪一个输出层具体负责。作者首先设计了min_size和max_size来确定某个gt到底由哪一层负责,具体设置是0, 64, 128, 256, 512和无穷大,也就是说对于第1个输出预测层而言,其stride=8,负责最小尺度的物体,对于第1层上面的任何一个空间位置点,如果有gt bbox映射到特征图上,满足0 < max(中心点到4条边的距离) < 64,那么该gt bbox就属于第1层负责,其余层也是采用类似原则。总结来说就是第1层负责预测尺度在0~64范围内的gt,第2层负责预测尺度在64~128范围内的gt,其余类推。通过该分配策略就可以将不同大小的gt分配到最合适的预测层进行学习。
第二步是需要确定在每个输出层上面,哪些空间位置是正样本区域,哪些是负样本区域。原版的fcos的正负样本策略非常简单粗暴:在bbox区域内的都是正样本,其余地方都是负样本,而没有忽略样本区域。可想而知这种做法不友好,因为标注本身就存在大量噪声,如果bbox全部区域都作为正样本,那么bbox边沿的位置作为正样本负责预测是难以得到好的效果的,显然是不太靠谱的(在文本检测领域,都会采用shrink的做法来得到正样本区域),所以后面又提出了center sampling的做法来确定正负样本,具体是:引入了center_sample_radius(基于当前stride参数)的参数用于确定在半径范围内的样本都属于正样本区域,其余区域作为负样本,依然没有定义忽略样本。默认配置center_sample_radius=1.5,如果第1层为例,其stride=8,那么也就是说在该输出层上,对于任何一个gt,基于gt bbox中心点为起点,在半径为1.5*8=12个像素范围内都属于正样本区域。其核心代码如下:
如果需要进行中心采样,那么基于采样半径比例×当前stride的范围内都属于正样本inside_gt_bbox_mask,其余样本全部属于负样本。可能很多人都有疑问:为啥不需要设置忽略区域?个人猜测原因可能是:1. 设置忽略区域,又需要增加一个超参;2.多了一个center-ness分支,可以很大程度抑制这部分区域对梯度的影响。3.间接的增加了正样本数目。不管咋说应该是作者实验后发现没有很大必要吧。
(3) 平衡loss设计
可以发现上述肯定存在大量正负样本不平衡问题,故作者对于分类分支采用了one-stage常用的focal loss;对于bbox回归问题,由于很多论文表明直接优化bbox比单独优化4个值更靠谱,故作者采用了GIOU loss来回归4个值,对于center-ness分支,采用的是CrossEntropyLoss,当做分类问题处理。
(4) 附加内容
center-ness作用比较大,从上面的正负样本定义就可以看出来,如果没有center-ness,对于所有正样本区域,其距离bbox中心不同远近的loss权重居然是一样的,这明显是违反直觉的,理论上应该越是远离Bbox中心的空间位置,其权重应该越小,作者实验也发现如果没有center-ness分支,会产生大量假正样本,导致很多虚检。center-ness本质就是对正样本区域按照距离gt bbox中心来设置权重,这是作者的做法,还有很多类似做法,不过有些是在Loss上面做文章,例如在ce loss基础上乘上一个类似预center-ness的权重来实现同样效果(例如Soft Anchor-Point Object Detection)。center-ness效果如下:
2.2 centernet
论文名称:Objects as Points
centernet也是非常流行的anchor-free论文,其核心是:一些场景的cv任务例如2d目标检测、3d目标检测、深度估计和关键点估计等等任务都可以建模成以物体中心点学习,外加上在该中心点位置处额外学习一些各自特有属性的通用做法。对于目标检测,可以将bbox回归问题建模成学习bbox中心点+bbox宽高问题,如下所示:
(1) head结构
centernet的输出也非常简单,其相比较于FCOS等算法,使用更大分辨率的输出特征图(缩放了4倍),本质上是因为其采用关键点检测思路做法,而关键点检测精度要高,通常是需要输出高分辨率特征图,同时不需要多尺度预测。其输出预测头包含3个分支,分别是
1. 分类分支h' x w' x (c+1),如果某个特定类的gt bbox的中心点落在某个位置上,那么该通道的对应位置值设置为1,其余为0;
2. offset分支h' x w' x 2,用于学习量化偏差,图像下采样时,gt bbox的中心点会因数据是离散的而产生偏差,例如gt bbox的中心点坐标是101,而由于输入和输出相差4倍,导致gt bbox映射到特征图上坐标由25.25量化为了25,这就出现了101-25x4=1个pix的误差,如果下采样越大,那么量化误差会越大,故可以使用offset分支来学习量化误差,这样可以提高预测精度。
3. 宽高分支h' x w' x 2,表示gt bbox的宽高。
其中1.2分支和cornetnet的做法完全相同。而由于objects as points的建模方式和FCOS的建模方式不一样,故centernet的正负样本定义就会产生很大区别。主要是宽高分支的通道数是2,而不是4,也就是说其输入到宽高分支的正样本其实会非常少,必须是gt bbox的中心位置才是正样本,左右偏移位置无法作为正样本,也没有啥忽略样本的概念,这个是和FCOS的最大区别。
(2) 正负样本定义
由于centernet特殊的建模方式,故其正负样本定义特别简单,不需要考虑多尺度、不需要考虑忽略区域,也不用考虑iou,正样本定义就是某个gt bbox中心落在哪个位置上,那么那个位置就是正样本,其余位置全部是负样本。
(3) 平衡Loss设计
前面说过目标检测所有论文的样本平衡策略都主要包括正负样本定义、正负样本采样和平衡loss设计,不管啥目标检测算法都省不了,对于centernet,其正负样本定义非常简单,可以看出会造成极其严重的正负样本不平衡问题,然后也无法像two-stage算法一样设计正负样本采样策略,那么平衡问题就必须要在loss上面解决。对于offset和宽高预测分支,其只对正样本位置进行监督,故核心设计就在平衡分类上面。对于分类平衡loss,首选肯定是focal loss了,但是还不够,focal loss的核心是压制大量易学习样本的权重,但是由于我们没有设置忽略区域,在正样本附近的样本,实际上非常靠近正样本,如果强行设置为0背景来学习,那其实相当于难负样本,focal loss会突出学这部分区域,导致loss难以下降、不稳定,同时也是没有必要的,因为我们的label虽然是0或者1的,但是在前向后处理时候是当做高斯热图(0~1之间呈现2d高斯分布特点)来处理的,我们学到最后的输出只要满足gt bbox中心值比附近区域大就行,不一定要学习出0或者1的图。
基于上述设定,在不修改分类分支label的情况下,在使用focal loss的情况下,作者的做法是对正样本附近增加惩罚,基于2d高斯分布来降低这部分权重,相当于起到了类似于忽略区域的作用。可以简单认为是focal focal loss。
可能很多人有疑问:明明label是0-1的,为啥学出来的会是高斯热图,而不是0-1热图? 我的分析是:如果不考虑附近区域,而是仅仅采用focal loss那么确实应该学出来的最接近0-1热图,但是由于基于距离gt bbox中心远近不同,设置了不同的惩罚系数,导致网络学习时候对于这部分学习出来的值关注程度不一样,可能就会产生这种现象,举例来说:即使采用上述label,最完美的输出应该是0或1的,但是实际上很难,对于偏离gt bbox附近一点点的位置,假设其预测输出为0,那么肯定是loss最低,但是可能训练不到那么好,那么由于其权重比较小,其学习出0.9,其实loss也不会太大,但是如果距离远一点的,其也学习出0.9,由于其loss权重比较大,就会迫使网络预测要变小一点点,例如变成0.8输出。基于这种权重分布,训练出来的热图可能就会按照1-loss权重的分布呈现,出现高斯热图。学习关键点中心,作者采用的是分类loss,不清楚如果直接采用回归loss,效果咋样,我觉得效果应该不会差。因为关键点检测一般都是采用l2回归loss直接监督在高斯热图上。并且因为宽高、offset分支其实也都是回归loss,三个分支都采用回归Loss不好吗?
还有一个问题:宽高和offset的监督仅仅在gt bbox中心位置,其余位置全部是忽略区域。这种做法其实很不鲁棒,也就是说bbox性能其实完全靠分类分支,如果分类分支学习的关键点有偏差,那么由于宽高的特殊监督特性,可能会导致由于中心点定位不准而带来宽高不准的情况(特别的如果中心点预测丢失了,那么宽高预测再准也没有用),后面有些论文有其他解决办法,
2.3 atss
论文名称:Bridging the Gap Between Anchor-based and Anchor-free Detection via Adaptive Training Sample Selection
本文写的非常好,作者试图分析问题:anchor-free和anchor-base算法的本质区别是啥?性能为啥不一样?最终结论是其本质区别就在于正负样本定义不同。只要我们能够统一正负样本定义方式,那么anchor-free和anchor-base就没有啥实际区别了,性能也是非常一致的。正负样本定义也是我写这篇文章的一个最大要说明的地方,因为其非常关键,要想彻底理解不同目标检测算法的区别,那么对于正负样本定义必须要非常清楚。
(1) head部分
由于这篇论文细节比较多,为了论文完整性,我这里大概说下,不重点描述。作者为了找出本质区别,采用了anchor-base经典算法retinanet以及anchor-free经典算法FCOS来说明,因为这两篇论文非常相似,最好进行对比。
由于FCOS是基于point进行预测,故可以认为就是一个anchor,为了公平对比,将retinanet的anchor也设置为1个(#A=1),将FCOS的训练策略移动到retinanet上面,可以发现性能依然retinanet低于fcos 0.8mAP。排除这个因素后,现在两个算法的区别是1.正负样本定义;2.回归分支中从point回归还是从anchor回归。从point回归就是指的每个点预测距离4条边的距离模式,而从anchor回归是指的retinanet那种基于anchor回归的模式。
后面有实验分析可以知道回归分支中从point回归还是从anchor回归对最终影响很小。ATSS的head部分结构如下
可以看出所有的参数其实就是retinanet和fcos参数的合并而已,没有新增参数。
(2) 正负样本定义
正负样本定义是本文的讨论重点。作者首先详细分析了retinanet和fcos的正负样本定义策略的不同,首先这两个算法都是多尺度预测的,故其实都包括两个步骤:gt分配给哪一层负责预测;gt分配给哪一个位置anchor负责预测。retinanet完全依靠统一的iou来决定哪一层哪一个位置anchor负责预测,而fcos显式的分为两步:先利用scale ratio来确定gt分配到哪一层,然后利用center sampling策略来确定哪些位置是正样本。具体细节请参见的retinanet和fcos的正负样本定义总结。这两种操作的细微差别会导致如下情形:
对于1和2两个输出预测层,retinanet采用统一阈值iou,可以确定上图蓝色1位置是正样本,而对于fcos来说,有2个蓝色1,表明fcos的定义方式会产生更多的正样本区域。这种细微差距就会导致retinanet的性能比fcos低一些。
对于retinanet算法,正负样本定义采用iou阈值,回归分支采用原始的anchor变换回归模式(box),mAP=37.0,采用fcos的point模式是36.9,说明到底是point还是box不是关键因素。但是如果换成fcos的正负样本定义模式,mAP就可以上升为37.8,和fcos一致了,说明正负样本定义的不同是决定anchor-base和anchor-free的本质区别。
既然找到了本质问题,作者分析肯定是fcos的正负样本定义策略比retinanet好,但是fcos算法需要定义超参scale constraint,比较麻烦,作者希望找到一种和fcos类似功能的正负样本定义算法,主要特定是几乎没有超参,或者说对超参不敏感,可以自适应,故作者提出ATSS算法。由于作者的设计可以认为是fcos正负样本定义策略的改进版本,故mmdetection的代码中也是针对fcos来说的,具体就是除了正负样本定义策略和fcos不一样外,其余全部相同,所以我们也仅仅需要关注atss部分代码就行。
流程比较简单,但是需要注意,由于依然需要计算iou,故anchor的设置不能少,只不过anchor仅仅用于计算正负样本区域而已,在计算loss时候还是anchor-free的,anchor默认设置就1个。主要是理解思想:
- 对于每个gt bbox,在每一个预测层上采样tokp个基于l2距离的位置,作为候选;
- 计算gt和每个候选anchor的iou;计算所有iou的均值和方差,相加变成iou阈值(每个gt都有一个自适应的iou阈值);
- 遍历每个候选anchor,如果该anchor大于iou阈值,并且anchor中心位置在gt bbox内部,那么这个就是正样本区域,其余全部是负样本。
均值(所有层的候选样本算出一个均值)代表了anchor对gt衡量的普遍合适度,其值越高,代表候选样本质量普遍越高,iou也就越大,而方差代表哪一层适合预测该gt bbox,方差越高越能区分层和层之间的anchor质量差异。均值和方差相加就能够很好的反应出哪一层的哪些anchor适合作为正样本。一个好的anchor设计,应该是满足高均值、高方差的设定。
如上图所示,(a)的阈值计算出来是0.612,采用该阈值就可以得到level3上面的才是正样本,是高均值高方差的。同样的如果anchor设置和gt不太匹配,计算出来的阈值为0.219,依然可以选择出最合适的正样本区域,虽然其属于低均值、低方差的。采用自适应策略依然可以得到相对好的正负样本,实现了自适应功能,至少可以保证每个GT一定有至少一个anchor负责对应。从这个设定来看,应该会出现某个gt在多个层上面都属于正样本区域,而没有限制必须在其中某个层预测,相当于增加了些正样本。K默认是9。
(3) 平衡loss设定
其loss函数设计完全和fcos一样,不再赘述。
2.4 spad
论文名称:Soft Anchor-Point Object Detection
本文可以认为是anchor-free论文的改进。其首先指出目前anchor-free算法存在的问题:1.attention bias,2.feature selection,并提出了相应的soft策略。由于其主要是修改了正负样本定义策略,故是本文分析的重点。
(1) head
本文属于anchor point类算法,即每个点都学习距离4条边的距离,这是标准的densebox算法流程,本质上和FCOS一样:
1.Attention bias
作者采用上面的网络进行训练,发现一个问题如下:
(b)是标准网络训练的分类confidence图,可以看出在靠近物体中心的四周会依然会产生大量confidence很高的输出,即没有清晰的边界,在训练过程中可能会抑制掉周围小的物体,导致小物体检测不出来或者检测效果很差。作者分析原因可能是在anchor-point方法在边界地方point进行回归,会存在特征不对齐问题或者说很难对齐。这个现象在FCOS没有加center-ness时候也出现了,FCOS的解决办法就是加入新的center-ness分支训练时候抑制掉,本文解决办法不一样,其通过加权方法。加权后效果如(c)。
2.Feature selection
特性选择问题其实是指的对于任何一个gt bbox,到底采用何种策略分配到不同的层级进行预测?目前目标检测的做法是基于启发式人工准则将实例分配到金字塔层次(retinanet),或将每个实例严格限制为单个层次(fcos),从而可能会导致特征能力的不充分利用。
作者通过训练发现:虽然每个GT只在特定层进行回归,但是其学出来的特征图是相似的,如上图所示,也就是说:一个以上金字塔等级的特征可以共同为特定实例的检测做出贡献,但是来自不同等级的贡献程度应该有所不同。这就是本文的出发点,不再强行判断哪一层进行回归了,而是每一层都进行回归,但是让网络自行学习到金字塔层级的权重。说了半天,作者仔细谈到了这两个问题,但思考下可以发现说的都是同一个问题,都是正负样本定义问题。attention bias说的是对于特定输出层内的正负样本定义问题,feature selection说的则是不同输出层间的正负样本定义问题,我们以前说的正负样本定义都是hard,这里解决办法都是soft。
(2) 正负样本定义
对于特定输出层内的soft正负样本定义问题,作者的解决办法是引入类似center-ness一样的权重,属于Loss层面改进,我们放在(3) 平衡loss分析;对于不同输出层间的soft正负样本定义问题,作者采用的是采用网络自动学习soft权重的做法。注意:输出层内hard正负样本定义,作者采用的依然和FCOS相同的策略,只不过正样本区域是通过4条边shrink得到,而不是center sampling。输出层间hard正负样本定义,作者没有用FCOS的分配策略,而是提出了新的soft代替hard。本文不再强行判断哪一输出层进行gt bbox回归了,而是每一层都进行所有gt bbox回归,但是让网络自行学习到金字塔层级的权重。
引入一个简单的网络来学习金字塔权重,具体做法是:利用gt bbox,映射到对应的特征图层,然后利用roialign层提出特征,在采用简单的分类器输出每个层级的权重。由于金字塔层数是5,故fc的输出是5。label设置上,这个思想的提出是参考FSAF(Feature Selective Anchor-Free Module for Single-Shot Object Detection)的做法,核心思想是不再人为定义具体是哪一层负责预测GT,而是根据loss最小的动态选择的那个层。本文借鉴上述思想,也是自动选择最适合的层。meta选择网络的独热码label不是人为提前计算好的,而是根据输出softmax层的值或者说loss来选择的,哪个输出节点loss最小,那么Label就设置为1,其余为0。整个meta选择网络和目标检测网络联合训练。
(3) 平衡loss设计
对于特定输出层内的soft正负样本定义问题,作者的解决办法是引入类似center-ness一样的权重,来对距离gt bbbx中心点进行惩罚。中心点权重最大,往外依次减少,其权重图如fcos里面所示:
从本质上来说和centernet的解决办法一模一样。
看过前面centernet 平衡分类loss分析的人可能有疑问:在centernet里面,其对focal loss的权重设置是在半径范围内,除中心点外,离中心点越近,权重最小,往外依次增加;但是这里的设计是正好相反的,其是离中心点越近,权重越大,往外依次减少。看起来是矛盾的?其实不是,千万不要忘记了label设计规则,centernet的分类label设置是除了中心点是1外,其余全部为0,而本文的label设置是不仅仅中心点是1,shrink附近区域的点也是1,其余全部是0,也就是说模糊区域中,centernet出发点认为是背景样本,而本文出发点认为是前景样本,所以其权重设置规则是正好相反的。
看到上图,就可以知道本文所有的操作了。对于特定层内的正负样本定义,原先是hard,现在通过引入权重变成了soft;对于层级间的正负样本定义,原先只会分配到特定层,其余层都0,现在引入了soft操作,权重是自己学到的。
通过网络学习到的层级间的权重,可以发现符合作者设定。
3 Guided Anchoring
论文名称:Region Proposal by Guided Anchoring
3.1 核心思想
ga这篇论文我觉得做的蛮好,先不说最终效果提升多少个mAP,他的出发点是非常不错的。anchor-base的做法都需要预设anchor,特别是对于one-stage而言,anchor设置的好坏对结果影响很大,因为anchor本身不会改变,所有的预测值都是基于anchor进行回归,一旦anchor设置不太好,那么效果肯定影响很大。而对于two-stage而言,好歹还有一个rcnn层,其可以对RPN的输出roi(动态anchor)进行回归,看起来影响稍微小一点。不管是one stage还是two-stage,不管咋预测,肯定都是基于语义信息来预测的,在bbox内部的区域激活值肯定较大,这种语义信息正好可以指导anchor的生成,也就是本文的出发点:通过图像特征来指导 anchor 的生成。通过预测 anchor 的位置和形状,来生成稀疏而且形状任意的 anchor。 可以发现此时的anchor就是动态的了。如果将faster rcnn进行改造,将RPN层替换为ga层,那肯定也是可以的,如果将retinanet或者yolo的预测层替换为ga,那其实就完全变成了anchor-free了。但是作者采用了一种更加优雅的实现方式,其采用了一种可以直接插入当前anchor-base网络中进行anchor动态调整的做法,而不是替换掉原始网络结构,属于锦上添花,从此anchor-base就变成了anchor-base混合anchor-free了(取长补短),我觉得这就是一个不错的进步。
3.2 网络设计
作者是以retinanet为例,但是可以应用于所有anchor-base论文中。核心操作就是在预测xywh的同时,新增两条预测分支,一条分支是loc(batch,anchor_num * 1,h,w),用于区分前后景,目标是预测哪些区域应该作为中心点来生成 anchor,是二分类问题,这个非常好理解,另一条分支是shape(batch,anchor_num * 2,h,w),用于预测anchor的形状。一旦训练好了,那么应该anchor会和语义特征紧密联系,如下所示:
其测试流程为:
- 对于任何一层,都会输出4条分支,分别是anchor的loc_preds,anchor的shape_preds,原始retinanet分支的cls_scores和bbox_preds
- 使用阈值将loc_preds预测值切分出前景区域,然后提取前景区域的shape_preds,然后结合特征图位置,concat得到4维的guided_anchors(x,y,w,h)
- 此时的guided_anchors就相当于retinanet里面的固定anchor了,然后和原始retinanet流程完全相同,基于guided_anchors和cls_scores、bbox_preds分支就可以得到最终的bbox预测值了。
可以发现和原始retinanet相比,就是多了anchor预测分支,得到动态anchor后,那就是正常的retinanet预测流程了。
3.3 loss设计
主要就是anchor的loc_preds和shape_preds的loss设计。
(1) loc_preds
anchor的定位模块非常简单,就是个二分类问题,希望学习出前景区域。这个分支的设定和大部分anchor-free的做法是一样的(例如fcos)。
- 首先对每个gt,利用FPN中提到的roi重映射规则,将gt映射到不同的特征图层上
- 定义中心区域和忽略区域比例,将gt落在中心区域的位置认为是正样本,忽略区域是忽略样本(模糊样本),其余区域是背景负样本,这种设定规则很常用,没啥细说的,如图所示:
- 采用focal loss进行训练
(2) loc_shape
loc_shape分支的目标是给定 anchor 中心点,预测最佳的长和宽,这是一个回归问题。先不用管作者咋做的,我们可以先思考下可以如何做,首先预测宽高,那肯定是回归问题,采用l1或者smooth l1就行了,关键是label是啥?还有哪些位置计算Loss?我们知道retinanet计算bbox 分支的target算法就是利用MaxIoUAssigner来确定特征图的哪些位置anchor是正样本,然后将这些anchor进行bbox回归。现在要预测anchor的宽高,当然也要确定这个问题。
第一个问题:如何确定特征图的哪些位置是正样本区域?,注意作者采用的anchor个数其实是1(作者觉得既然是动态anchor,那么个数其实影响不会很大,设置为1是可以的错),也就是说问题被简化了,只要确定每个特征图的每个位置是否是正样本即可。要解决这个问题其实非常容易,做法非常多,完全可以按照anchor-free的做法即可,例如FOCS,其实就是loc_preds分支如何确定正负样本的做法即可,确定中心区域和忽略区域。将中心区域的特征位置作为正样本,然后直接优化预测输出的anchor shape和对应gt的iou即可。但是论文没有这么做,我觉得直接按照fcos的做法来确定正样本区域,然后回归shape,是完全可行。本文做法是采用了ApproxMaxIoUAssigner来确定的,ApproxMaxIoUAssigner和MaxIoUAssigner非常相似,仅仅多了一个Approx,其核心思想是:利用原始retinanet的每个位置9个anchor设定,计算9个anchor和gt的iou,然后在9个anchor中采用max操作,选出每个位置9个iou中最高的iou值,然后利用该iou值计算后续的MaxIoUAssigner,此时就可以得到每个特征图位置上哪些位置是正样本了。简单来说,ApproxMaxIoUAssigner和MaxIoUAssigner的区别就仅仅是ApproxMaxIoUAssigner多了一个将9个anchor对应的iou中取最大iou的操作而已。
对于第二个问题:正样本位置对应的shape target是啥,其实得到了每个位置匹配的gt,那么对应的target肯定就是Gt值了。该分支的loss是bounded iou loss,公式如下:
上面写的非常简陋,很多细节没有写,放在1.5节代码分析中讲解。
3.4 结果
可以看出非常符合预期。
3.5 代码分析
(1) head
本文代码分析以retinanet为主,网络骨架和neck就没啥说的了,直接截图:
就是ResNet+FPN结构,输出5个分支进行预测。stride为[8, 16, 32, 64, 128]。对于head部分,可以对比retinanet的head部分进行查看:
左边是GARetinaHead,右边是RetinaHead,可以看出配置除了loss有区别外,都是一样的。head部分的forward非常简单,和retinanet相比就是多了两个shape_pred, loc_pred分支:
关于feature_adaption的作用作者在论文分享中:Guided Anchoring: 物体检测器也能自己学 Anchor(https://zhuanlan.zhihu.com/p/55854246)说的很清楚了,我就不写了。反正forward后就可以4个分支输出。
(2) loss计算
(2-1) anchor的loc分支loss计算
loc输出特征图大小是(batch,1,h,w),本质上是一个二分类器,用于找出语义前景区域。
核心参数是中心区域占据比例center_ratio=0.2,忽略区域占比ignore_ratio=0.5.首先需要计算loc分支的target,方便后面计算loss,对应的函数是ga_loc_target,由于代码比较多,不太好写,我只能写个大概流程出来。
有了每个特征图上,每个位置是正负还是忽略样本的结果,就可以针对预测的Loc特征图计算focal loss了:
(2-2) anchor的shape分支loss计算
这个分支稍微复杂一点点。首先我们要先熟悉下train_cfg
对于GA分支,主要包括ApproxMaxIoUAssigner和RandomSampler,而原始的retinanet分类和回归分支没有任何改变,不再赘述。ApproxMaxIoUAssigner是用来近似计算shape特征图分支上哪些位置负责预测gt bbox,而RandomSampler主要目的不是用来平衡正负样本的,因为shape分支监督的只有正样本,没有啥平衡问题。上述两个类非常关键,理解清楚了才能理解最核心的shape target计算过程。
(1) 计算5个特征图上,每个位置9个anchor,组成anchor_list
可以明显发现approx_generators是每个位置9个anchor,而square_generators每个位置是1个anchor,且是正方形。为了方便区分,你可以认为squares_list存储的就是每一层的还原基数而已,和anchor没啥关系的,只不过可以等价实现而已。而guided_anchors_list其实就是在squares_list基础上结合loc预测和shape预测得到的动态anchor,用于训练原始的retinanet的分类和回归分支。而如何利用squares_list、loc_pred和shape_pred得到最终的动态anchor,做法非常简单,如下所示(测试阶段也是这个流程):
(3) 计算shape target
在得到squares_list、approxs_list和gt_bboxes,下面核心就是计算shape target了。函数是:
计算shape target的流程包括2步:
1、确定哪些位置是正样本,通过ApproxMaxIoUAssigner类实现;
2. 每个正样本位置的label,通过RandomSampler实现。
这两个操作看起来和faster rcnn的rpn阶段的loss计算相同,其实仅仅思想相同而已,但是实现差别还是很大的。
假设你已经了解了MaxIoUAssigner的实现过程,而ApproxMaxIoUAssigner的实现是继承自MaxIoUAssigner的,其核心差别是:
而MaxIoUAssigner仅仅有以下一行而已:
overlaps = bbox_overlaps(gt_bboxes, bboxes)
ApproxMaxIoUAssigner的做法是对于每个位置,先计算9个anchor和gt bbox的iou,然后max选择最大iou,将anchor=9变成anchor=1(因为预测就是只有1个anchor),然后在这个overlaps基础上再进行MaxIoUAssigner分配机制,从而确定哪些位置是正样本,同时会记录每个位置负责的gt bbox索引,方便后面计算。下一步是RandomSampler函数,但是要非常注意:retinanet的是RandomSampler调用过程:
assign_result = bbox_assigner.assign(anchors, gt_bboxes,gt_bboxes_ignore, gt_labels)
而ga分支的调用过程是:
# 确定了哪些位置是正样本区域后,需要加入正样本区域的squares值。注意这里加入的anchor不是近似anchor,而是squares
sampling_result = bbox_sampler.sample(assign_result, squares, gt_bboxes)
函数内部实现是一样的,但是由于传入的参数不一样,所有解释就不一样了。第一行的输入是anchor和gt bbox,意思是随机采样正负样本,并且同时将gt bbox作为label,后面直接计算回归loss,但是注意ga分支的输入是assign_result和squares,而不是assign_result和gt bbox,也不是assign_result和approxs。也就是说咱们暂时把每个正样本位置shape预测值的target认为是squares值,后面还会进一步操作。
到这里为止,就已经知道了shape_target返回的各个值含义了。bbox_anchors_list存储的是所有正样本位置的squares值,bbox_gts_list是对应的gt bbox值,在得到所有需要的值后终于可以开始计算shape target的loss了。
bbox_anchor其实就是bbox_anchors_list,将bbox_anchors_list和shape_pred经过delta2bbox就还原得到真实的bbox预测值了,只不过由于本分支仅仅用于预测shape,故bbox_deltas的前两个维度一直是0,loss_shape是BoundedIoULoss。
到此,核心代码就分析完了。稍微难理解的就是shape target的计算过程了。
4 yolo-asff
论文名称:Learning Spatial Fusion for Single-Shot Object Detection
源码地址:https://github.com/ruinmessi/ASFF
简介
先贴性能:
首先可以看出是非常强的。虽然本文题目重点是说ASFF层的牛逼地方,但是我觉得看本文,重点不在这里,而是yolov3的强baseline。
通过一些训练技巧,将yolov3从33.0mAP,提升到38.8mAP,我觉得这个才是重点需要学习的地方。这其实反映出一个明显问题:骨架的改进固然重要,但是训练技巧绝对要引起重视,很多新提出的算法搞了半天提升了1个mAP点,还不如从训练技巧上面想点办法来的快(在人脸检测领域就会针对人脸尺度问题针对性的提出大量训练技巧,是非常高效的),毕竟训练技巧只会影响训练过程,对推理没有任何额外负担,何乐不为。
ASFF
本文先分析不那么重要的部分,即本文最大改进ASFF(Adaptively Spatial Feature Fusion)操作,其实熟悉BiFpn的人应该马上就能get到idea了,我觉得本质上没有啥区别。FPN操作是一个非常常用的用于对付大小尺寸物体检测的办法,作者指出FPN的缺点是不同尺度之间存在语义gap,举例来说基于iou准则,某个gt bbox只会分配到某一个特定层,而其余层级对应区域会认为是背景(但是其余层学习出来的语义特征其实也是连续相似的,并不是完全不能用的),如果图像中包含大小对象,则不同级别的特征之间的冲突往往会占据要素金字塔的主要部分,这种不一致会干扰训练期间的梯度计算,并降低特征金字塔的有效性。
一句话就是:目前这种concat或者add的融合方式不够科学。本文觉得应该自适应融合,自动找出最合适的融合特征,如下所示:
简要思想就是:原来的FPN add方式现在变成了add基础上多了一个可学习系数,该参数是自动学习的,可以实现自适应融合效果,类似于全连接参数。ASFF具体操作包括 identically rescaling和adaptively fusing。定义FPN层级为l,为了进行融合,对于不同层级的特征都要进行上采样或者下采样操作,用于得到同等空间大小的特征图,上采样操作是1x1卷积进行通道压缩,然后双线性插值得到;下采样操作是对于1/2特征图是采样3 × 3 convolution layer with a stride of 2,对于1/4特征图是add a 2-stride max pooling layer然后引用stride 卷积。Adaptive Fusion
下面讲解具体操作:
(1) 首先对于第l级特征图输出cxhxw,对其余特征图进行上下采样操作,得到同样大小和channel的特征图,方便后续融合
(2) 对处理后的3个层级特征图输出,输入到1x1xn的卷积中(n是预先设定的),得到3个空间权重向量,每个大小是nxhxw
(3) 然后通道方向拼接得到3nxhxw的权重融合图
(4) 为了得到通道为3的权重图,对上述特征图采用1x1x3的卷积,得到3xhxw的权重向量
(5) 在通道方向softmax操作,进行归一化,将3个向量乘加到3个特征图上面,得到融合后的cxhxw特征图
(6) 采用3x3卷积得到输出通道为256的预测输出层
ASFF层学习得到的各种特征可视化效果如下:
强baseline
YOLOv3包括darknet53骨架网络和3层特征金字塔网络构成的3个尺度输出。
首先采用基于Bag of freebies for training object detection neural networks里面提出的训练策略来改进性能,主要包括 the mixup algorithm , the cosinelearning rate schedule和 the synchronized batch normalization。 其次,由于最新论文表示iou loss对于边界框回归效果好,故作者也额外引入了一个iou loss来优化bbox。最后,由于GA论文(Region proposal by guided anchoring)指出采用语义向导式的anchor策略可以得到更好的结果,故作者也引入了GA操作来提升性能。可以看出,结合这些策略后,在coco上面可以得到38.8的mAP,速度仅仅慢了一点点(多了GA操作),可谓是非常强大,这也反应出训练策略对最终性能的影响非常大。
the mixup algorithm , the cosinelearning rate schedule和 the synchronized batch normalization这三个策略非常常见,没啥好说的。额外引入一个iou loss也是常规操作。我们重点分析GA的实现。为啥要重点分析GA操作呢?因为作者实现的GA和原始论文的GA有点不同,很值得分析。
loss代码分析
对应的代码是YOLOv3Head.py
首先和GA一样,也是有FeatureAdaption,用于对动态anchor特征进行自适应。
(1) 初始化函数
anchors里面存储的就是原始yolov3的9组anchor,但是特别需要注意的是这里实现的anchor个数是4个,而不是GA原文的1个anchor,这个小差别会导致后面代码有些差别。按照GA论文做法,其实1个anchor就足够了。而且需要注意这里的GA分支没有输出Loc,仅仅有shape预测。原因是loc分支的目的仅仅是用于进行前后景提取,是个二分类问题,但是由于yolo有confidence分支,其有前后景提取功能,故不再需要loc分支。 loss函数方面,就是多了shape预测的IOUWH_loss函数,以及bbox回归额外引入的IOUloss,其余相同。
(2) forward函数
(2-1) 输出预测值
对ASFF层输出的每一层特征图xin,进行GA分支推理,并且经过Feature_adaption,得到最终的bbox预测输出output,由于wh预测肯定是大于0的,故作者采用了exp函数强制大于0.此时就得到了**wh_pred(batch,4,2,h,w)和output(batch,4,5+class,h,w)**。
(2-2) 将预测anchor变换到原图尺度,得到guide anchor
(2-3) 前向模式下基于预测anchor直接进行回归即可得到最终bbox
(2-4) 训练模式下准备target 先准备数据:
计算匹配anchor和confidence mask
理解下面的操作才是理解了本文核心:
前面所有准备都好了后,就是计算loss了:
可以看出前两个loss是额外加入的。
GA的引入可以实现:
(1) 在anchor设置不合理时候,动态引导anchor预测分支得到更好的anchor
(2) 在anchor设置合理时候,可以加速收敛,且可以进一步refine 默认anchor
GA实现过程非常好,思路清晰,很好理解,可以实现anchor-base混合anchor-free,发挥各自的优势。后续会进行各种对比实验,验证GA在yolo中的引导作用。
#SmartDet、Miti-DETR和Few-Shot Object Detection
论文地址:
SmartDet:https://arxiv.org/pdf/2201.04235.pdf
Miti-DETR:https://arxiv.org/pdf/2112.13310.pdf
Few-Shot Object Detection:https://arxiv.org/pdf/2201.02052.pdf
1. SmartDet
链接: https://pan.baidu.com/s/1hyLejH0ewBLxo3QnJJ776Q 密码: 8r4n
移动设备越来越依赖于通过深度神经网络(DNN)进行目标检测(OD)来执行关键任务。由于它们的高度复杂性,这些DNN的执行需要过多的时间和精力。低复杂度目标跟踪(OT)可与OD一起使用,后者定期应用以生成用于跟踪的“新”参考。但是,使用OD处理的帧会产生较大的延迟,这可能会使参考过时并降低跟踪质量。
在这里,研究者建议在这种情况下使用边缘计算,并建立并行的OT(在移动设备上)和OD(在边缘服务器上)进程,以适应大的OD延迟。提出了Katch-Up,这是一种新颖的跟踪机制,可以提高系统对过度OD延迟的恢复能力。然而,Katch-Up在显着提高性能的同时,也增加了移动设备的计算负载。因此,研究者设计了SmartDet,这是一种基于深度强化学习(DRL)的低复杂度控制器,可以学习控制资源利用率和OD性能之间的权衡。SmartDet将与当前视频内容和当前网络状况相关的上下文相关信息作为输入,以优化OD offloading的频率和类型,以及Katch-Up利用率。
在由作为移动设备的JetSon Nano和作为边缘服务器的GTX 980 Ti组成的真实测试平台上广泛评估SmartDet,通过Wi-Fi链接连接。实验结果表明,SmartDet在跟踪性能——mAR和资源使用之间取得了最佳平衡。对于具有完全Katch-Up使用和最大通道使用的基线,研究者仍然将mAR增加4%,同时使用与Katch-Up相关的50%的通道和30%的电源资源。对于使用最少资源的固定策略,研究者在1/3的帧上使用Katch-Up时将mAR提高了20%。
2.Miti-DETR
链接: https://pan.baidu.com/s/1P86IGv2jBgL-jnJp6iy0IA 密码: w0mi
使用Transformers进行目标检测(DETR)和相关工作达到甚至超过了高度优化的FasterRCNN基线以及自注意网络架构。受纯self-attention具有强烈的归纳偏差的证据的启发,这会导致Transformer在网络深度方面失去表达能力,研究者通过在Transformer中应用可能的直接映射连接,提出了一种具有缓解self-attention机制的Transformer架构减轻等级崩溃的架构,以抵消特征表达损失并增强模型性能。
研究者将此提议应用于目标检测任务,并开发了一个名为Miti-DETR的模型。MitiDETR将每个注意力层的输入保留到该层的输出中,以便“非注意力”信息参与任何注意力传播。形成的残差自注意力网络解决了两个关键问题:
- 最大程度地阻止自注意力网络退化到rank-1
- 进一步多样化参数更新的路径分布,以便更容易地学习注意力
Miti-DETR在具有挑战性的COCO目标检测数据集上显着提高了现有基于DETR模型的平均检测精度和收敛速度。此外,所提出的带有残差自注意力网络的转换器可以很容易地推广或插入其他相关的任务模型,而无需特定的定制。
3.Few-Shot Object Detection
链接: https://pan.baidu.com/s/15i6cfrPXNv4AwVXB-jLu-g 密码: u9ro
attention-based FSOD method
Few-Shot Object Detection(FSOD)是计算机视觉中一个快速发展的领域。它包括查找给定类集的所有出现,每个类只有几个带注释的示例。已经提出了许多方法来应对这一挑战,其中大多数是基于注意力机制的。然而,种类繁多的经典目标检测框架和训练策略使得方法之间的性能比较变得困难。
Alignment Attention Fusion (AAF) module
特别是,对于基于注意力的FSOD方法,比较不同注意力机制对性能的影响是很费力的。该paper旨在弥补这一不足。为此,提出了一个灵活的框架,以允许实施文献中可用的大多数注意力技术。为了正确引入这样的框架,首先提供了对现有FSOD方法的详细回顾。然后在框架内重新实现一些不同的注意力机制,并与所有其他固定参数进行比较。
#多级特征重复使用大幅度提升检测精度
近年来,在利用深度卷积网络检测目标方面取得了显著进展。然而,很少有目标检测器实现高精度和低计算成本。今天分享的干货,就有研究者提出了一种新的轻量级框架,即多级特性重用检测器(MFRDet),它可以比两阶段的方法达到更好的精度。它还可以保持单阶段方法的高效率,而且不使用非常深的卷积神经网络。该框架适用于深度和浅层特征图中包含的信息的重复利用,具有较高的检测精度。
(a)仅使用单尺度特征进行预测,(b)整合来自高级和低级特征图的信息,(c)从不同尺度的特征图生成预测,(d)就是今天分享的多层特征重用模块可以获得不同尺度的特征图。
- Shot learning
在深度学习领域,特别是目标检测领域,数据集的建设是至关重要的。进行了许多优秀和有价值的研究,改进了多元数据集的理论和实践。有研究者创建了一种有效的从Web学习方法来解决问题的数据集偏差,没有手动注释。这可能提供了一种帮助zero-shot学习的方法。zero-shot学习研究的主要问题是目标分类问题和目标检测问题。目前,在zero-shot学习中仍存在一些需要解决的问题,如domain shift problem, hubness problem和semantic gap问题。zero-shot学习通常将视觉特征嵌入其他模态空间,或将多个模型空间映射到一个共同的潜在空间,使用最近邻思想对看不见目标进行分类,这对目标检测器有很高的需求。
One-shot学习的目的是从一个或只有少数的训练图像中学习有关目标类别的信息。与zero-shot学习不同,One-shot学习依赖于先验知识,比如物体识别,它需要对形状和外观的先验知识。
新框架
- SSD分析
SSD和Yolo一样都是采用一个CNN网络来进行检测,但是却采用了多尺度的特征图,其基本架构如下图所示。下面将SSD核心设计理念总结为以下三点:
SD基本框架
(1)采用多尺度特征图用于检测
所谓多尺度采用大小不同的特征图,CNN网络一般前面的特征图比较大,后面会逐渐采用stride=2的卷积或者pool来降低特征图大小,这正如上图所示,一个比较大的特征图和一个比较小的特征图,它们都用来做检测。这样做的好处是比较大的特征图来用来检测相对较小的目标,而小的特征图负责检测大目标,如下图所示,8x8的特征图可以划分更多的单元,但是其每个单元的先验框尺度比较小。
不同尺度的特征图
(2)采用卷积进行检测
(3)设置先验框
在Yolo中,每个单元预测多个边界框,但是其都是相对这个单元本身(正方块),但是真实目标的形状是多变的,Yolo需要在训练过程中自适应目标的形状。而SSD借鉴了Faster R-CNN中anchor的理念,每个单元设置尺度或者长宽比不同的先验框,预测的边界框(bounding boxes)是以这些先验框为基准的,在一定程度上减少训练难度。一般情况下,每个单元会设置多个先验框,其尺度和长宽比存在差异,如图5所示,可以看到每个单元使用了4个不同的先验框,图片中猫和狗分别采用最适合它们形状的先验框来进行训练,后面会详细讲解训练过程中的先验框匹配原则。
SSD的先验框
新框架(MFRDet)
如上面所述,有许多利用尝试观察和充分利用金字塔特征。图(b)显示了最常见的模式之一。这种类型经过了历史验证,大大提高了传统检测器的性能。但是这种设计需要多个特征合并过程,从而导致大量额外的计算。
今天分享的框架提出了一种轻量级、高效的多级特征重用(MFR)模块(如图(d)所示)。该模块能够充分利用不同尺度的特征图,集成了深、浅层的特征,提高了检测性能。特征重用模块可简要说明如下:
S的选择:
在初步设计它们时,需要考虑以下几个关键因素。首先,应该选择要重用的图层。在传统的SSD中,作者部署了conv4_3、fc7和另外四个SSD层进行预测。6个选定的特征地图的比例表包括38×38、19×19、10×10、5×5和1×1。在不同的SSD中,这些层是独立的,今天这个研究者不同意。研究者相信,小尺度特征图中存在的语义信息在尺度变换后的检测中仍然有效。选择了六个预测层和conv5_3层作为框架要重用的源层。从下表中,可以得出一个明确的结论,即重用conv3_3将降低检测精度。高分辨率特征图没有足够的高级语义信息,因此放弃了对其信息的重用。
Ti的转换策略:
在传统的SSD中,规模为38×38、语义信息很少的浅层conv4_3负责小目标识别。conv4_3层被设置为需要包含更深层语义信息的基本层。策略因特征图的标准而不同。首先,对每个源层应用Conv1×1来减小特征尺寸。然后,在Conv1×1层后,通过双线性插值,将尺度小于38×38的层(四个SSD_layers和fc7层)放入相同大小的38×38中。这样,所有的源特性都会转换为相同的大小。
Ψt的选择:
在转换策略Ti的过程完成后,创建了新的变换特征图。它们是conv4_3、conv5_3、fc7、conv8_2、conv9_2、conv10_2和conv11_2。有两种方法可以将新转换的特征映射合并在一起。通过实验验证,这两种方法都能得到良好的结果。从上表中,可以了解到连接似乎更适合我们的模型。
实验
在coco数据集上的检测可视化结果
#Weighted boxes fusion
目标检测佳作:Weighted boxes fusion, 目标检测是计算机视觉系统中的一项关键任务,在自动驾驶、医学成像、零售、安全、人脸识别、机器人技术等领域都有广泛的应用。目前,基于神经网络的模型被用于对特定类目标的实例进行定位和分类。
1、动机&摘要
当不需要实时推理时,模型的整合就有助于获得更好的结果。在这项工作中,研究者提出了一种新的方法来结合目标检测模型的预测:加权边界框融合。新提出的算法利用所有提出的边界框的置信度分数来构造平均的边界框。
2、背景
目标检测是一种计算机视觉技术,它处理图像和视频中特定类别的语义目标的实例。检测是一系列实际应用的基本任务,包括自主驾驶、医学成像、机器人、安全等。该任务将定位与分类相结合。目标检测模型通常会返回目标的候选位置、类标签和置信度分数。使用非极大抑制(NMS)方法选择预测框。首先,它会根据它们的置信度分数对所有的检测框进行分类。然后,选择具有最大置信值的检测框。同时,所有其他有明显重叠的检测框都会被过滤掉。它依赖于一个硬编码的阈值来丢弃冗余的边界框。最近的一些工作使用了一个可微分的模型来学习NMS,并引入了soft-NMS来提高过滤性能。
3、相关工作
- Non-maximum suppression (NMS)
回顾下NMS和Soft-NMS
经典NMS最初第一次应用到目标检测中是在RCNN算法中,其实现严格按照搜索局部极大值,抑制非极大值元素的思想来实现的,具体的实现步骤如下:
- 设定目标框的置信度阈值,常用的阈值是0.5左右
- 根据置信度降序排列候选框列表
- 选取置信度最高的框A添加到输出列表,并将其从候选框列表中删除
- 计算A与候选框列表中的所有框的IoU值,删除大于阈值的候选框
- 重复上述过程,直到候选框列表为空,返回输出列表
其中IoU(Intersection over Union)为交并比,如上图所示,IoU相当于两个区域交叉的部分除以两个区域的并集部分得出的结果。下图是IoU为各个取值时的情况展示,一般来说,这个score > 0.5 就可以被认为一个不错的结果了。
下面,通过一个具体例子来说明经典NMS究竟做了什么。下图的左图是包含一个检测目标(王闹海)的实例图片。其中的绿色矩形框代表了经过目标检测算法后,生成的大量的带置信度的Bounding box,矩形框左下角的浮点数即代表该Bounding box的置信度。在这里,使用Python对经典NMS算法实现,并应用到该实例中去。当NMS的阈值设为0.2时,最后的效果如下图中右图所示。
def nms(bounding_boxes, Nt):if len(bounding_boxes) == 0:return [], []bboxes = np.array(bounding_boxes)# 计算 n 个候选框的面积大小x1 = bboxes[:, 0]y1 = bboxes[:, 1]x2 = bboxes[:, 2]y2 = bboxes[:, 3]scores = bboxes[:, 4]areas = (x2 - x1 + 1) * (y2 - y1 + 1)# 对置信度进行排序, 获取排序后的下标序号, argsort 默认从小到大排序order = np.argsort(scores)picked_boxes = [] # 返回值while order.size > 0:# 将当前置信度最大的框加入返回值列表中index = order[-1]picked_boxes.append(bounding_boxes[index])# 获取当前置信度最大的候选框与其他任意候选框的相交面积x11 = np.maximum(x1[index], x1[order[:-1]])y11 = np.maximum(y1[index], y1[order[:-1]])x22 = np.minimum(x2[index], x2[order[:-1]])y22 = np.minimum(y2[index], y2[order[:-1]])w = np.maximum(0.0, x22 - x11 + 1)h = np.maximum(0.0, y22 - y11 + 1)intersection = w * h# 利用相交的面积和两个框自身的面积计算框的交并比, 将交并比大于阈值的框删除ious = intersection / (areas[index] + areas[order[:-1]] - intersection)left = np.where(ious < Nt)order = order[left]return picked_boxes
soft-NMS
经典NMS是为了去除重复的预测框,这种算法在图片中只有单个物体被检测的情况下具有很好的效果。然而,经典NMS算法存在着一些问题:对于重叠物体无法很好的检测。当图像中存在两个重叠度很高的物体时,经典NMS会过滤掉其中置信度较低的一个。如下图所示,经典NMS过滤后的结果如下下图所示:
而我们期望的结果是两个目标都被算法成功检测出来。
为了解决这类问题,Jan Hosang,等人提出了Soft-NMS算法。Soft-NMS的算法伪代码如图5所示。其中红色框为经典NMS的步骤,而绿色框中的内容为Soft-NMS改进的步骤。可以看出,相对于经典NMS算法,Soft-NMS仅仅修改了一行代码。当选取了最大置信度的Bounding box之后,计算其余每个Bounding box与Bounding box的I ou值,经典NMS算法的做法是直接删除Iou大于阈值的Bounding box;而Soft-NMS则是使用一个基于Iou的衰减函数,降低Iou大于阈值Nt的Bounding box的置信度,IoU越大,衰减程度越大。
def soft_nms(bboxes, Nt=0.3, sigma2=0.5, score_thresh=0.3, method=2):# 在 bboxes 之后添加对于的下标[0, 1, 2...], 最终 bboxes 的 shape 为 [n, 5], 前四个为坐标, 后一个为下标res_bboxes = deepcopy(bboxes)N = bboxes.shape[0] # 总的 box 的数量indexes = np.array([np.arange(N)]) # 下标: 0, 1, 2, ..., n-1bboxes = np.concatenate((bboxes, indexes.T), axis=1) # concatenate 之后, bboxes 的操作不会对外部变量产生影响# 计算每个 box 的面积x1 = bboxes[:, 0]y1 = bboxes[:, 1]x2 = bboxes[:, 2]y2 = bboxes[:, 3]scores = bboxes[:, 4]areas = (x2 - x1 + 1) * (y2 - y1 + 1)for i in range(N):# 找出 i 后面的最大 score 及其下标pos = i + 1if i != N - 1:maxscore = np.max(scores[pos:], axis=0)maxpos = np.argmax(scores[pos:], axis=0)else:maxscore = scores[-1]maxpos = 0# 如果当前 i 的得分小于后面的最大 score, 则与之交换, 确保 i 上的 score 最大if scores[i] < maxscore:bboxes[[i, maxpos + i + 1]] = bboxes[[maxpos + i + 1, i]]scores[[i, maxpos + i + 1]] = scores[[maxpos + i + 1, i]]areas[[i, maxpos + i + 1]] = areas[[maxpos + i + 1, i]]# IoU calculatexx1 = np.maximum(bboxes[i, 0], bboxes[pos:, 0])yy1 = np.maximum(bboxes[i, 1], bboxes[pos:, 1])xx2 = np.minimum(bboxes[i, 2], bboxes[pos:, 2])yy2 = np.minimum(bboxes[i, 3], bboxes[pos:, 3])w = np.maximum(0.0, xx2 - xx1 + 1)h = np.maximum(0.0, yy2 - yy1 + 1)intersection = w * hiou = intersection / (areas[i] + areas[pos:] - intersection)# Three methods: 1.linear 2.gaussian 3.original NMSif method == 1: # linearweight = np.ones(iou.shape)weight[iou > Nt] = weight[iou > Nt] - iou[iou > Nt]elif method == 2: # gaussianweight = np.exp(-(iou * iou) / sigma2)else: # original NMSweight = np.ones(iou.shape)weight[iou > Nt] = 0scores[pos:] = weight * scores[pos:]# select the boxes and keep the corresponding indexesinds = bboxes[:, 5][scores > score_thresh]keep = inds.astype(int)return res_bboxes[keep]
后期我们详细给大家说说NMS一系列知识!
4、Weighted Boxes Fusion
在这里,我们描述了新的边界框融合方法:加权边界框融合(WBF)。假设,我们已经绑定了来自N个不同模型的相同图像的框预测。或者,我们对相同图像的原始和增强版本(即垂直/水平反射,数据增强)有相同模型的N个预测)。WBF工作如下步骤:
NMS和Soft-NMS都排除了一些框,而WBF则使用了所有框。因此,它可以修复所有模型都预测不准确的情况。本案例如下图所示。NMS/Soft-NMS将只留下一个不准确的框,而WBF将使用所有预测的框来融合它。
5、实验结果
[46]: ZFTurbo. Coco wbf benchmark. https://github. com/ZFTurbo/Weighted-Boxes-Fusion/tree/master/benchmark, 2020.
#目标检测x2
检测是视觉的基底,不管你应用在什么领域,检测识别是最基础也是最重要的技术之一,就好比人类的眼睛,只要你看到了,才传输到大脑更新迭代学习,促使我们认识世界万物。所以,我们一定要掌握目标检测技术之一!
类似于人类的快速学习能力,少样本学习使视觉系统能够通过使用少量样本进行训练来理解新概念。源自对具有单个视觉对象的图像进行元学习的领先方法。由于复杂的背景和一张图像中的多个目标的混淆,它们很难促进few-shot目标检测/分割的研究。
还有一个技术就是距离度量学习(DML)。已成功地应用于目标分类,无论是在训练数据丰富的标准体系中,还是在每个类别仅用几个例子表示的few-shot场景中。有研究者提出了一种新的DML方法,在一个端到端训练过程中,同时学习主干网络参数、嵌入空间以及该空间中每个训练类别的多模态分布。将提出的DML架构作为分类头合并到一个标准的目标检测模型中,证明了新方法在处理few-shot目标检测问题上的有效性。
在目标检测,有研究者提出了一种灵活而通用的方法来实现这些任务。其通过提出基于RoI(感兴趣区域)特征而不是完整图像特征的元学习来扩展Faster/Mask R-CNN。使Faster/Mask R-CNN变成元学习器来完成任务。
具体来说,引入了一个Predictor-head Remodeling Network (PRN)共享Faster/Mask R-CNN的主干网络。PRN接收包含few-shot目标及其边界框或masks的图像,以推断它们的类注意力向量。这些向量对RoI特征采取通道方式的软注意力,重塑那些R-CNN Predictor-head以检测或分割与这些向量所代表的类别一致的目标。
技术基础
在few-shot检测实验中,引入了新的检测类别。这是通过使用从为这些类别提供的少量训练示例(k个用于k-shot检测的示例)的前景RoI中计算的嵌入向量来替换所学习的代表(对应于旧类别)来实现的。还研究了微调新提出的模型的效果和baseline的few-shot学习。下图概略地说明了few-shot检测方法。
提出了一种新的子网结构,用于联合训练嵌入空间和该空间中的混合分布集,每个类别都有一个(多模态)混合。该体系结构对基于DML的目标分类和few-shot目标检测都有较好的改善作用;其次,提出了一种基于DML分类器头的目标检测器的设计方法,该方法能够识别新的类别,并将其转化为一种few-shot检测器。检测器训练批次通常被限制在每个GPU一个图像,不允许在类别内容方面进行批次控制。这种控制是目前任何使用情景训练的few-shot学习者所需要的。这反过来又使得在端到端训练的检测器中使用这些方法具有挑战性。在新提出的方法中,代表集充当“内部存储器”,在训练批次之间传递信息。Few-shot目标检测旨在从极少数以前unseen类的注释示例中快速检测新目标,已经引起了社区的重大研究兴趣。大多数现有方法都采用 Faster R-CNN 作为基本检测框架,但由于缺乏针对数据稀缺场景的定制考虑,它们的性能往往不能令人满意。
就好比上面的框架,仔细研究了传统的Faster R-CNN,并从两个正交的角度分析了它的矛盾,即多阶段(RPN 与 RCNN)和多任务(分类与定位)。为了解决这些问题,我们提出了一种简单而有效的架构,名为Decoupled Faster R-CNN (DeFRCN)。
新框架
首先,查询集图片经过特征提取网络和RPN网络(与Faster/Mask R-CNN中相同)得到感兴趣区域的特征图zi。然后支持集图像和对应的真实标签图经过预测器重建模网络(PRN)得到每个类别对应的类别注意力向量(class-attentive vectors),PRN网络的主体部分与Faster/Mask R-CNN的特征提取网络结构相同且权重共享,得到对应特征图后,通过逐元素Sigmoid函数得到对应的注意力向量vc。最后将RPN网络输出的感兴趣区域特征图zi和PRN网络输出的注意力向量vc通过逐通道相乘的方式进行融合,最后再利用Faster/Mask R-CNN中预测头得到对应个检测图或分割图。
假设PRN表示为:
Meta R-CNN中元优化过程的说明性实例
RePMet的结构中提出一种子网结构和相应的损失,使我们能够训练一个DML嵌入与多模态混合分布用于计算类后验在产生的嵌入空间。然后这个子网成为一个基于DML的分类器头部,它可以附加在分类器或检测主干的顶部。需要注意的是,DML子网是与生成功能的主干一起训练的。上图描述了所提出的子网的体系结构。
Network architectures used. (a) Network for DML based classification. (b) Network for few-shot detection; its backbone is FPN+DCN with deformable ROI-align.实验可视化结果
相关文章:
51c~目标检测~合集1
我自己的原文哦~ https://blog.51cto.com/whaosoft/12371248 #目标检测x1 又一个发现 都不知道是第几了 是一个高效的目标检测 动态候选较大程度提升检测精度 目标检测是一项基本的计算机视觉任务,用于对给定图像中的目标进行定位和分类。 论文地址:…...
前端工程化面试题
说一下模块化方案 模块化是为了解决代码的复用和组织问题,可以说有了模块化才让前端有了工程的概念,模块化要解决两大问题 代码隔离和依赖管理,从node.js最早发布的commonjs 到浏览器端的 AMD,CMD 规范以及兼容的 UMD 规范,再到现…...
【Visual Studio】下载安装 Visual Studio Community 并配置 C++ 桌面开发环境的图文教程
引言 Visual Studio 是一个面向 .NET 和 C 开发人员的综合性 Windows 版 IDE,可用于构建 Web、云、桌面、移动应用、服务和游戏。 安装步骤 访问 Visual Studio 的官方下载页面: https://visualstudio.microsoft.com/zh-hans/downloads/运行已下载的 V…...
010Editor:十六进制编辑器
介绍 世界上最好的十六进制编辑器和出色的文本编辑器 010 Editor 是用于处理文本和二进制数据的终极工具包。 添加模板 模板库https://www.sweetscape.com/010editor/repository/templates/ 先下载一个ELF 模板 运行模板...
Vscode中Github Copilot无法使用
现象 Copilot侧边栏显示要登录,但是点击"github登录"没有反应与Copilot对话,报错如下: Unexpected token o, "[object Rea"... is not valid JSON解决方案 在网上怎么找都没找到类似的问题,最后发现是Vsco…...
<项目代码>YOLOv8表情识别<目标检测>
YOLOv8是一种单阶段(one-stage)检测算法,它将目标检测问题转化为一个回归问题,能够在一次前向传播过程中同时完成目标的分类和定位任务。相较于两阶段检测算法(如Faster R-CNN),YOLOv8具有更高的…...
利用Msfvenom实现对Windows的远程控制
1.实验准备 kali安装 Apache2(如果尚未安装): sudo apt install apache2 启动 Apache2 服务: sudo systemctl start apache2确认 Apache2 的默认网页可以访问: 打开浏览器并访问 http://<你的Kali IP>ÿ…...
Java Iterator和for区别详解和常见问题及解决方式
在 Java 中,Iterator 是一个用于遍历集合元素的接口。它为访问集合中的元素提供了一种标准的方法,不管具体集合的实现如何。本文将详细讲解 Iterator 的使用、其与 for 循环的区别,以及在遍历集合时的删除操作可能带来的问题,并提…...
川渝地区软件工程考研择校分析
C哥专业提供——计软考研院校选择分析专业课备考指南规划 通过最新数据分析,5所高校软件工程专业2025年考研难度从高到低预计为: 电子科技大学 >> 四川大学 > 重庆大学 ≈ 西南交通大学 > 西南大学 对于想考川渝地区985但核心目标为优先上岸的考生,建议重点考虑西…...
快捷键记忆
快捷键记忆 文章目录 快捷键记忆前言一、PotPlayer快捷键二、电脑快捷键总结 前言 提示:以下是本篇文章正文内容: 一些软件的快捷键经常忘记,写这篇文章的目的是帮助我忘记的时候来查看。 顺序实时更新: 一、PotPlayer快捷键 Po…...
Flutter鸿蒙next 状态管理高级使用:深入探讨 Provider
✅近期推荐:求职神器 https://bbs.csdn.net/topics/619384540 🔥欢迎大家订阅系列专栏:flutter_鸿蒙next 💬淼学派语录:只有不断的否认自己和肯定自己,才能走出弯曲不平的泥泞路,因为平坦的大路…...
JMeter实战之——模拟登录
本篇介绍使用JMeter 如何对需要登录的站点进行压力测试。 基本Session验证的机制 使用session进行请求验证的机制是一种常见的Web应用认证方式。 该认证方式的主要内容如下: 一、登录过程 用户输入:用户在登录页面输入用户名和密码。发送请求&#x…...
智能台灯设计(一)原理图设计
1. 前言 作者最近突发奇想,想自己做一个小台灯,设想的功能有:带锂电池可充电、可以调节亮度,后续通过增加WIFI模块实现手机控制开关功能。目前先实现最简单的功能,有时间再一步步完善吧。 2. 原理图设计 充电芯片使用…...
数据库查询返回结果集及其元数据信息:ResultSet 和 ResultSetMetaData 深度解析
全文目录: 开篇语📌 目录🌟 前言📝 摘要📚 简介🔍 概述🧩 核心源码解读1️⃣ 创建数据库连接2️⃣ 执行查询获取结果集3️⃣ 读取查询数据4️⃣ 获取元数据信息 💻 案例分析…...
2.插入排序(斗地主起牌)
一、思想 扑克牌起牌 代码: 二、时间复杂度: 最好情况(已经排序好的):T O(N) 最坏情况(完全逆序):T O(N^2) 三、优劣: 严格的大小比较之后才进行错位插入&#x…...
漫谈编程小白如何成为大神:夯实基础,开启通神之路
在当今数字化时代,编程已成为一项基本技能,对于大学新生而言,掌握编程能力不仅能够为学术研究提供支持,还能为未来的职业生涯开辟广阔天地。然而,面对琳琅满目的编程语言和学习资源,新生们往往会感到迷茫和…...
基于机器学习的个性化电影推荐系统【源码+安装+讲解+售后+文档】
【1】系统介绍 研究背景 随着互联网技术的迅速发展,数字娱乐内容特别是电影和电视剧的数量急剧增加。用户在享受丰富内容的同时,也面临着选择困难的问题,即“信息过载”。传统的搜索和分类方法已经无法满足用户日益增长的个性化需求。与此同…...
企业如何配合好等级保护测评工作?
企业如何配合好等级保护测评工作,是一个涉及多方面因素的系统性任务。等级保护测评,简称等保测评,是中国对信息和信息系统安全的重要管理手段和评估制度。通过这一制度,企业可以全面了解其信息系统的安全状况,及时发现…...
Could not find artifact cn.hutool:hutool-all:jar:8.1 in central 导入Hutool报错
<!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all --><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.9</version></dependency> 引入hutool 8.1版本的工具…...
【功能安全】汽车功能安全个人认证证书
目录 1、证书 2、课程信息 📖 推荐阅读 1、证书 汽车功能安全工程师去拿类似莱茵、SGS、南德颁发的证书,如下: 2、课程信息 一般上什么课程了,课程信息大概如下: 汽车功能安全工程师认证课 (3天&#…...
axios直接上传binary
axios直接上传二进制文件 、 axios直接上传apk、axios直接上传binary postman中的参数选项中有个binary,平常我们很少使用,可能有的同学遇到这种情况不太会了,认为后端应该有个字段名来接收,或者使用 Formdata,但其实…...
量化交易API接口是什么?如何申请和应用?
炒股自动化:申请官方API接口,散户也可以 python炒股自动化(0),申请券商API接口 python炒股自动化(1),量化交易接口区别 Python炒股自动化(2):获取…...
语义分割:YOLOv11的分割模型训练自己的数据集(从代码下载到实例测试)
文章目录 前言一、环境搭建二、构建数据集三、修改配置文件①数据集文件配置②模型文件配置 四、模型训练和测试模型训练模型验证模型推理 总结 前言 专栏目录:YOLOv11改进目录一览 | 涉及卷积层、轻量化、注意力、损失函数、Backbone、SPPF、Neck、检测头等全方位改…...
Python爬虫:从入门到精通
Python爬虫:从入门到精通 在数字时代,信息就如同水源,源源不绝。然而,当你想要从海量的信息中汲取有价值的“水”,你会发现这并不是一件容易的事。这就是为什么网络爬虫出现了。它们帮助我们在网络的海洋中航行&#…...
Web组态软件
Web组态软件是近年来前端开发领域的一股新兴力量,它以其独特的魅力吸引着越来越多的开发者们。那么,Web组态软件到底是什么?它有哪些特点?我们又该如何选择和使用它呢?下面,就让我们一起探讨这些问题。 一…...
Java中为什么要私有化构造方法
为什么要私有化构造方法 要私有化的方法不是来描述一类事物的,创建没有任何意义 解决方案: 提示:这里填写该问题的具体解决方案: 为什么要将构造方法私有化? 问:如果要限制一个类对象产生,即&…...
【大数据学习 | kafka】kafuka的基础架构
1. kafka是什么 Kafka是由LinkedIn开发的一个分布式的消息队列。它是一款开源的、轻量级的、分布式、可分区和具有复制备份的(Replicated)、基于ZooKeeper的协调管理的分布式流平台的功能强大的消息系统。与传统的消息系统相比,KafKa能够很好…...
2-petalinux2018.3摸索记录-petalinux rootfs
1Filesystem Packages文件系统软件包2Petalinux Package GroupsPetalinux软件包组3Image Features镜像特性4apps应用程序5user packages用户软件包6Petalinux RootFS SettingsPetalinux根文件系统设置 Filesystem Packages(文件系统软件包) 这个选项主要…...
RHCE作业二
1.要求: 配置nginx服务通过ip访问多网站 2. 1关闭防火墙 2创建ip 3配置 4创建文件 5测试...
GPS/北斗时空安全隔离装置(卫星时空防护装置)使用手册
GPS/北斗时空安全隔离装置(卫星时空防护装置)使用手册 GPS/北斗时空安全隔离装置(卫星时空防护装置)使用手册 时空安全隔离装置采用先进的防欺骗抗干扰技术,能够有效检测识别欺骗干扰信号,并快速对异常信号进行关断、切换,消除欺骗干扰影响。…...
主页制作语言缩写/惠州seo招聘
看起来很麻烦,做起来并不难的题 以下设:$a_i\frac{a_i}{100},b_i\frac{b_i}{100}$ 显然,如果$b_i0$的话,直接求$\Pi a_i$就是答案。 解决反射问题是这个问题的关键 我们显然可以认为一束光透过之后,可以等其他的光一起…...
python基础教程第二版/aso优化什么意思是
java基础之main方法解读: 一、深入理解main方法:(由java虚拟机调用) 解释main方法的形式:public static void main (String [] args){} 1.java虚拟机需要调用类的main()方法,所以该…...
用wordpress做视频网站/郑州全域静态管理
sql是声明性语言:首先要把这个概念记在脑中:“声明”。 SQL 语言是为计算机声明了一个你想从原始数据中获得什么样的结果的一个范例,而不是告诉计算机如何能够得到结果。 SQL 语言声明的是结果集的属性,计算机会根据 SQL 所声明的…...
安卓app软件开发教程/广州seo网站排名
chrome下运行编写的JavaScript代码时,在工具javascript控制台下有时会出现“Uncaught SyntaxError: Unexpected identifier ”的报错,经过我反复查看代码最后得出,原来是代码中缺少一个“,”(英文逗号)。 后经在网上查…...
如何做内部优惠券网站/网页制作源代码
hadoop distcp -i hdfs://192.168.10.211:9000/fileinfo hdfs://192.168.24.46:9000/fileinfo distcp [OPTIONS] <srcurl>* <desturl> -i Ignore failures 转载于:https://www.cnblogs.com/yanghuahui/p/3490713.html...
wordpress ios shared/河北软文搜索引擎推广公司
数着星星 盼着月亮2021国考笔试成绩终于出了! 成绩今日公布中公锦鲤给大家带来好运哭惹!也太快了吧!只能骂骂咧咧地打开查询入口▽▽▽扫码进入成绩查询入口国考成绩对手成绩&同岗分差万人报名产生千人大岗的XXX局究竟会有多少大神产生…...