开着翻斗逛钟楼 發表於 2025-12-24 21:25:00

吴恩达深度学习课程四:计算机视觉 第三周:检测算法 (三)交并比、非极大值抑制和锚框

<p>此分类用于记录吴恩达深度学习课程的学习笔记,目前已完结,点击进入全集目录<br>
课程相关信息链接如下:</p>
<ol>
<li>原课程视频链接:[双语字幕]吴恩达深度学习deeplearning.ai</li>
<li>github课程资料,含课件与笔记:吴恩达深度学习教学资料</li>
<li>课程配套练习(中英)与答案:吴恩达深度学习课后习题与答案</li>
</ol>
<p>本篇为第四课的第三周内容,3.6到3.8的内容。</p>
<hr>
<p>本周为第四课的第三周内容,这一课所有内容的中心只有一个:<strong>计算机视觉</strong>。应用在深度学习里,就是专门用来进行图学习的模型和技术,是在之前全连接基础上的“特化”,也是相关专业里的一个重要研究大类。<br>
<strong>这一整节课都存在大量需要反复理解的内容和机器学习、数学基础。</strong> 因此我会尽可能的补足基础,用比喻和实例来演示每个部分,从而帮助理解。<br>
第三周的内容将从<strong>图像分类</strong>进一步拓展到<strong>目标检测(Object Detection)</strong> 这一更具挑战性的计算机视觉任务。<br>
与分类任务只需回答“图中有什么”不同,目标检测需要同时解决“ <strong>有什么</strong>”以及“<strong>在什么位置</strong>”两个问题,因此在模型结构设计、训练方式和评价标准上都更为复杂。<br>
本篇的内容关于交并比、非极大值抑制和锚框,是对上一篇目标检测算法对的一些补充。</p>
<h1 id="1交并比intersection-over-unioniou">1.交并比(Intersection over Union,IoU)</h1>
<p>在分类任务中,我们介绍过一些评估指标来评估分类模型的性能,现在当任务从分类发展到检测,自然也要有相应的评估指标来评估“定位的准不准”以及“有多准”。<br>
因此,交并比就是我们针对目标检测任务而定义的评估指标之一,它的字面意思是“交集面积除以并集面积”,用于<strong>衡量两个边界框的重叠程度</strong>,我们直接使用它的同时也以它为基础来构建目标检测任务的一些更专业的评估指标。<br>
这个概念并不难理解,我们来看课程中里例子:<br>
<img src="https://img2024.cnblogs.com/blog/3708248/202512/3708248-20251224213500003-1877654745.png" alt="image" loading="lazy"></p>
<p>很显然,交并比越大,就代表我们预测的目标位置越接近真实值,模型的效果就越好:</p>
<ul>
<li><span class="math inline">\(IoU = 0\)</span>:完全不重叠</li>
<li><span class="math inline">\(IoU = 1\)</span>:完全重合</li>
</ul>
<p>并且,不同于之前我们使用的准确率,F1 分数等指标仅仅用作评估,我们<strong>还可以依靠交并比进一步提升模型性能。</strong><br>
怎么做到?就是下面这一部分:</p>
<h1 id="2-非极大值抑制non-maximum-suppressionnms">2. 非极大值抑制(Non-Maximum Suppression,NMS)</h1>
<h2 id="21-多个重叠预测框现象">2.1 多个重叠预测框现象</h2>
<p>在上一篇对 YOLO 算法的基础介绍中,我们提到过,算法会将输入图像划分为网格,每个网格独立预测本网格内的目标,而我们在标注样本的标签时,会把目标归入目标中心点所在网格中。<br>
就像这样:<br>
<img src="https://img2024.cnblogs.com/blog/3708248/202512/3708248-20251224211946108-849893869.png" alt="image.png" loading="lazy"><br>
但是,<strong>这只是我们标注的逻辑</strong>。<br>
在推理阶段,模型并不知道“哪个网格被分配了哪个目标”,它只是在每个网格上独立判断“这里是否存在目标”,并回归一个可能的边界框。<br>
因此,当网格内存在目标特征时,它就可能给出一个较高置信度的预测。<br>
所以就会出现这样一种现象:<strong>模型明明已经“找对了目标”,却给出了很多个高度重叠的预测框。</strong><br>
就像这样:<br>
<img src="https://img2024.cnblogs.com/blog/3708248/202512/3708248-20251224212035813-1830544111.png" alt="image.png" loading="lazy"><br>
如果我们直接把这些结果全部输出,会发生什么?<br>
答案是:<strong>一个目标被检测成了很多个目标</strong>。<br>
显然,这并不是我们想要的结果。<br>
所以,就有了非极大值抑制,来看看如何使用它。</p>
<h2 id="22-应用非极大值抑制">2.2 应用非极大值抑制</h2>
<p>非极大值抑制的作用,<strong>就是在这些高度重叠的“候选框”中,只保留最有代表性的那一个,其余的全部抑制掉。</strong><br>
这里的“高度重叠”,就是通过我们刚刚介绍的 <strong>IoU</strong> 来量化的。<br>
我们来看一下<strong>非极大值抑制的标准流程</strong>:</p>
<ol>
<li><strong>按置信度排序</strong> :将所有预测框按照分类得分从高到低排序。</li>
<li><strong>选出当前得分最高的框,作为最终结果之一</strong> :这个框被认为是对某个目标的“最可信描述”。</li>
<li><strong>计算该框与其他所有框的 IoU</strong> :如果某个框与当前框的 IoU 大于预设阈值(如 0.5),说明它们指向的是同一个目标。</li>
<li><strong>抑制(删除)这些高 IoU 的框</strong> :只保留与当前框重叠程度较低的预测框。</li>
<li><strong>重复上述过程,直到没有候选框为止。</strong></li>
</ol>
<p>再演示一下,来看课程里这个例子:<br>
<img src="https://img2024.cnblogs.com/blog/3708248/202512/3708248-20251224212024741-539068866.png" alt="image.png" loading="lazy"></p>
<p>于是,应用非极大值抑制后,我们就得到了: <strong>数量合理、位置准确、重复度极低的检测结果。</strong><br>
<img src="https://img2024.cnblogs.com/blog/3708248/202512/3708248-20251224212047262-605630129.png" alt="image.png" loading="lazy"></p>
<h2 id="23-预测框在传播后的两次筛选">2.3 预测框在传播后的两次筛选</h2>
<p>在应用了非极大值抑制后,你就会发现,我们在对目标的预测过程中,为了得到更准确的结果,进行了两次筛选。</p>
<h4 id="1第一次筛选基于置信度的是否存在目标">(1)第一次筛选:基于置信度的“是否存在目标”</h4>
<p>在模型完成正向传播后,每一个网格都会给出一组预测,其中首先便是目标存在概率 <span class="math inline">\(p_c\)</span><br>
这一步中,通常会先进行一次<strong>置信度阈值过滤</strong>:当 <span class="math inline">\(p_c\)</span> 较低时,说明模型认为这里更可能是背景,这些预测框会被<strong>直接丢弃</strong>。<br>
只有 <span class="math inline">\(p_c\)</span> 高于阈值的预测,才会进入下一阶段。<br>
这一步的作用是:<strong>快速过滤掉大量明显的背景区域,减少后续计算量。</strong></p>
<h4 id="2第二次筛选基于-iou-的非极大值抑制">(2)第二次筛选:基于 IoU 的非极大值抑制</h4>
<p>经过第一次筛选后,剩下的预测框已经基本都是:置信度较高且确实“命中目标特征”的候选框</p>
<p>现在要解决的问题就是:<strong>它们可能仍然在描述同一个目标。</strong><br>
于是,就需要第二次筛选——<strong>非极大值抑制</strong>,即通过 IoU 进行比较,只保留最具代表性的预测框,其余全部抑制掉。<br>
这样,我们最终才能得到一组:数量合理、位置准确、对应真实目标的检测结果。<br>
<img src="https://img2024.cnblogs.com/blog/3708248/202512/3708248-20251224212026068-887925461.png" alt="image.png" loading="lazy"></p>
<p>打个比方来理解:<br>
第一次筛选是在问:<strong>“你确定你看到了东西吗?”</strong><br>
第二次筛选是在问:<strong>“你们是不是都在看同一个东西?”</strong></p>
<h2 id="24-多个检测目标类别得分">2.4 多个检测目标:类别得分</h2>
<p>我们现在已经知道了如何对单目标检测任务进行非极大值抑制,可要是扩展到多分类呢?<br>
这时,你会发现,我们不能再用 <span class="math inline">\(p_c\)</span> 的大小来代表检测目标的得分了。<br>
因此,我们针对多目标检测任务中选择置信度最高的检测框引入了一个新概念:<strong>类别得分</strong>。<br>
它的公式并不难:</p>
<p></p><div class="math display">\[\text{Class Score}_n = p_c \times c_n
\]</div><p></p><p>我们直接通过一个例子来说明它:<br>
假设我们正在做一个 <strong>三分类目标检测任务</strong>,需要检测: 人(Person)、车(Car)、狗(Dog)<br>
对于某一个预测框,模型给出了如下输出:</p>
<p></p><div class="math display">\[p_c = 0.8
\]</div><p></p><p>表示:<strong>该位置存在某个目标的置信度为 0.8。</strong><br>
同时,模型在“存在目标”的前提下,给出了类别预测概率:</p>
<p></p><div class="math display">\[(c_{\text{person}}, c_{\text{car}}, c_{\text{dog}}) = (0.1, 0.7, 0.2)
\]</div><p></p><p>在多类别目标检测中,<strong>真正用于排序和筛选预测框的不是 <span class="math inline">\(p_c\)</span>,而是分类得分</strong>,代入上面的数值,我们得到:</p>
<ul>
<li>人(Person):<span class="math inline">\(0.8 \times 0.1 = 0.08\)</span></li>
<li>车(Car):<span class="math inline">\(0.8 \times 0.7 = 0.56\)</span></li>
<li>狗(Dog):<span class="math inline">\(0.8 \times 0.2 = 0.16\)</span></li>
</ul>
<p>该预测框最终会被判定为:<strong>“车”</strong>,它在“车”这一类别下的得分为:<strong>0.56</strong><br>
因此,在执行非极大值抑制时:该框会<strong>参与“车”类别的非极大值抑制</strong>,并与其他“车”类预测框<strong>按照 0.56 的得分进行排序和抑制</strong>。</p>
<p>总结一下:<strong>在多类别目标检测中,<span class="math inline">\(p_c\)</span> 只负责判断“是否存在目标”,真正用于筛选、排序和执行 NMS 的,是结合了类别信息的“分类得分”。</strong></p>
<h1 id="3-锚框anchor-boxes">3. 锚框(Anchor Boxes)</h1>
<h3 id="31-为什么需要锚框">3.1 为什么需要锚框?</h3>
<p>在前面的内容中,我们默认了一个前提:<strong>每个网格只预测一个边界框。</strong><br>
这种设定在“目标数量较少、尺度差异不大”的场景下是可以工作的,但它很快就会暴露出一个致命问题:<strong>一个网格里,可能同时存在多个不同目标。</strong><br>
如果同一个网格中:</p>
<ul>
<li>既有一个<strong>高而瘦的人</strong>。</li>
<li>又有一辆<strong>矮而宽的车</strong>。<br>
<img src="https://img2024.cnblogs.com/blog/3708248/202512/3708248-20251224212009849-543883718.png" alt="image.png" loading="lazy"><br>
这时,如果我们仍然强制这个网格只预测一个边界框,那么显然,很可能二者都无法被较好地定位。<br>
这不是训练不充分的问题, 而是<strong>面对多目标检测,输出空间本身不够用</strong>。<br>
<strong>锚框的引入,本质上就是为了解决多目标检测中,同一网格中出现多个不同形态的目标而导致的定位混乱现象。</strong></li>
</ul>
<h3 id="32-如何使用锚框">3.2 如何使用锚框?</h3>
<p>锚框的思想可以用一句话概括:<strong>不再让模型“从零开始”去猜边界框,而是让它在多个“预设形态”的参考框基础上进行微调。</strong></p>
<p>具体做法是:在每一个网格位置<strong>预先放置</strong> <span class="math inline">\(K\)</span> 个<strong>形状不同的参考框</strong>,这些参考框就是<strong>锚框</strong>。<br>
例如:我们预先知道预测目标一个是人,一个是汽车,于是便预先为每个网格设置两个锚框:</p>
<ul>
<li>一个偏高偏瘦,用来预测行人位置。</li>
<li>一个偏矮偏宽,用来预测汽车位置。</li>
</ul>
<p>就像课程里这样:<br>
<img src="https://img2024.cnblogs.com/blog/3708248/202512/3708248-20251224212000010-336183907.png" alt="image.png" loading="lazy"><br>
于是,一个网格不再只输出<strong>一组预测</strong>,而是输出 <strong><span class="math inline">\(K\)</span> 组预测结果</strong>,分别对应这 <span class="math inline">\(K\)</span> 个锚框。</p>
<h3 id="33-当同一个网格中可能出现多个目标时的标签变化">3.3 当同一个网格中可能出现多个目标时的标签变化</h3>
<p>我们知道,在之前,我们假定<strong>一个网格中只会出现一种目标</strong>,因此,我们这样定义标签:</p>
<p></p><div class="math display">\[y =(p_c, b_x,b_y,b_h,b_w,c_1, c_2, \dots, c_n)
\]</div><p></p><p>但很显然,当一个网格中可能出现多个目标时,一组标签是不够用的。如果网格里同时出现了行人和汽车,我们就要为它们各自设置一组标签来让网络学习。<br>
同理,当一个网格不再只输出<strong>一组预测</strong>,而是输出 <strong><span class="math inline">\(K\)</span> 组预测结果</strong>时,我们就要为其设置 <span class="math inline">\(K\)</span> 组标签:</p>
<p></p><div class="math display">\[y =K \times(p_c, b_x,b_y,b_h,b_w,c_1, c_2, \dots, c_n)
\]</div><p></p><p>就像这样:<br>
<img src="https://img2024.cnblogs.com/blog/3708248/202512/3708248-20251224212323495-1504344305.png" alt="image.png" loading="lazy"></p>
<p>现在,我想你可能会有一个问题:<strong>我通过更改标签适应了同一网格中存在多种目标的情况,那网络不是就可以直接学每个目标的检测了吗?锚框是不是不设置也没有问题?</strong></p>
<p>别急,我们了解完锚框的具体使用逻辑,这个问题自然会迎刃而解。</p>
<h2 id="34-标签如何使用锚框">3.4 标签如何使用锚框</h2>
<p>首先,在多锚框机制下,<strong>每个网格不仅有 <span class="math inline">\(K\)</span> 个预测框,还对应 <span class="math inline">\(K\)</span> 组标签</strong>。这些标签并不是随意分配的,而是与锚框紧密对应,形成训练的监督信号:</p>
<ul>
<li>对于每个网格内的每个锚框,计算它与所有<strong>真实目标框</strong>的 IoU。</li>
<li>将 IoU 最大的目标分配给该锚框,该锚框就是<strong>正样本锚框</strong>。</li>
<li>如果某个锚框与任何目标 IoU 都低于阈值,则该锚框为<strong>负样本</strong>,其标签 <span class="math inline">\(p_c=0\)</span>,其他参数忽略。</li>
</ul>
<p>这样,我们就完成了<strong>锚框和要检测的目标的匹配</strong>。</p>
<p>同时,锚框机制还把位置信息的学习<strong>转换为锚框中心和大小的微调</strong>。也就是说,网络不再直接去预测目标在图像中的绝对位置和尺寸,而是预测目标相对于锚框的偏移量和缩放比例。<br>
它并不是改变标签里的位置信息的语义,而是<strong>通过运算将原本的绝对尺度转换为相对锚框的偏移量并学习。</strong><br>
我们这里不摆复杂的公式,了解原理即可。<br>
这部分其实和残差学习的逻辑有一定的相似之处:只需预测相对于参考框的微调量,降低了学习难度,使网络更容易收敛并稳定检测多目标。</p>
<p>现在,我们再来解释上面的问题:<br>
你会发现 : <strong>锚框其实是我们人为帮助模型进行目标检测的一种手工设计。</strong><br>
如果你只是简单地在标签中为同一网格增加多组目标信息,而不使用锚框,就会遇到这样几个问题:</p>
<ol>
<li><strong>没有锚框的目标匹配,输出与标签会匹配混乱。</strong></li>
<li><strong>没有锚框的偏移学习,面对多目标任务会收敛困难。</strong></li>
<li><strong>没有锚框的“个性定制”,网络多目标检测的能力不足。</strong></li>
</ol>
<h2 id="35-小结">3.5 小结</h2>
<p>这部分内容较多,我们简单小结一下:<br>
锚框的引入是为了<strong>解决单网格只能预测一个目标而无法处理同网格多目标的问题</strong>,通过在每个网格预设多个不同形状的参考框,让网络只需<strong>预测目标相对于锚框的偏移量和类别概率</strong>,从而简化学习任务并提高收敛性。<br>
每个网格对应 <span class="math inline">\(K\)</span> 个锚框,也就对应 <span class="math inline">\(K\)</span> 组标签,<strong>通过与真实目标的 IoU 匹配确定正负样本</strong>。<br>
如果没有锚框,网络在多目标检测中容易出现目标匹配混乱、偏移量学习困难和收敛不稳定等问题。<br>
锚框本质上是一种<strong>人为设计的参考机制</strong>,用来帮助网络更高效、稳定地完成多目标检测。</p>
<h1 id="4-总结">4. 总结</h1>
<table>
<thead>
<tr>
<th>概念</th>
<th>原理</th>
<th>比喻</th>
</tr>
</thead>
<tbody>
<tr>
<td>交并比(IoU)</td>
<td>衡量预测框与真实框重叠程度,计算公式为交集面积除以并集面积,越大表示预测越准确</td>
<td>就像量尺量两个重叠物体的重合面积,越大说明测量越精确</td>
</tr>
<tr>
<td>非极大值抑制(NMS)</td>
<td>对候选预测框进行筛选,先按置信度排序,保留最可信预测框,再根据 IoU 删除重叠度高的框</td>
<td>第一次筛选:问“你确定看到东西了吗?”,第二次筛选:问“你们是不是都在看同一个东西?”</td>
</tr>
<tr>
<td>置信度(<span class="math inline">\(p_c\)</span>)</td>
<td>预测该网格存在目标的概率</td>
<td>判断“这里有没有东西”</td>
</tr>
<tr>
<td>类别得分(Class Score)</td>
<td>用 <span class="math inline">\(p_c \times c_n\)</span> 表示某类别的最终得分,用于多类别 NMS 排序</td>
<td>确定目标的“身份得分”,选择最可能的类别进行抑制</td>
</tr>
<tr>
<td>锚框(Anchor Boxes)</td>
<td>在每个网格预设多个不同形状的参考框,让网络只需预测相对于锚框的偏移量和类别概率,每个锚框与真实目标通过 IoU 匹配形成正负样本</td>
<td>就像给网络提供模板,让它只需微调而不是从零猜测,类似残差学习只学变化量</td>
</tr>
<tr>
<td>标签变化</td>
<td>每个网格输出 <span class="math inline">\(K\)</span> 组预测,对应 <span class="math inline">\(K\)</span> 组标签,分别匹配不同锚框</td>
<td>原本一个网格只需写一份作业,现在每个模板都写一份作业</td>
</tr>
<tr>
<td>锚框作用</td>
<td>解决单网格多目标、提高收敛性、稳定训练</td>
<td>给网络参考框,让它“照模板微调”而不是盲目猜测</td>
</tr>
</tbody>
</table><br><br>
来源:https://www.cnblogs.com/Goblinscholar/p/19394617
頁: [1]
查看完整版本: 吴恩达深度学习课程四:计算机视觉 第三周:检测算法 (三)交并比、非极大值抑制和锚框