动手学深度学习——多尺度锚框
1. 前言在前面的学习中我们已经知道了锚框的基本思想在图像的每个位置预先生成若干个不同大小、不同宽高比的候选框再由模型判断这些框中是否包含目标并进一步修正位置。但是新的问题很快就出现了。现实中的目标并不是统一大小的而是有明显的尺度差异。例如在一张街景图像中近处的汽车可能很大远处的行人可能很小路边的交通标志可能更小如果我们只在一种固定尺度上生成锚框就很难同时覆盖这些不同大小的目标。因此目标检测中提出了一个非常重要的思想在不同尺度的特征图上生成不同尺度的锚框用来检测不同大小的目标。这就是本节要学习的内容多尺度锚框。2. 为什么需要多尺度锚框2.1 真实目标大小差异很大这是最根本的原因。在同一张图中不同目标可能有完全不同的尺寸小目标远处行人、鸟、交通灯中等目标自行车、摩托车大目标汽车、公交车、整个人脸如果所有锚框都设置成差不多大小那么就会出现两种情况框太大不适合检测小目标框太小不适合检测大目标所以锚框的尺度必须根据目标大小变化。2.2 深层特征图和浅层特征图的感受野不同卷积神经网络越往后特征图分辨率通常越小但感受野越大。这意味着浅层特征图分辨率高适合定位小目标深层特征图分辨率低但语义更强适合检测大目标因此不同层的特征图本来就适合负责不同尺度的目标。如果能在这些不同尺度的特征图上分别生成锚框那么检测效果就会更合理。2.3 单一尺度难以兼顾检测效果只用单一尺度的锚框理论上也能覆盖部分目标但效果通常不理想。因为模型必须在同样的候选框设置下同时适配大目标和小目标这会增加学习难度。而多尺度锚框相当于把任务分工了小目标交给高分辨率特征图大目标交给低分辨率特征图这样检测会更加自然。3. 多尺度锚框的核心思想多尺度锚框的本质可以概括成一句话在不同大小的特征图上以每个像素为中心生成不同尺度的锚框。这里有两个重点第一不同大小的特征图例如4 × 42 × 21 × 1这些特征图尺度不同。第二不同尺度的锚框在较大的特征图上生成较小的锚框在较小的特征图上生成较大的锚框。这样整套锚框系统就能覆盖从小目标到大目标的不同情况。4. 李沐这里是怎么讲“多尺度”的在《动手学深度学习》中这一节的核心不是一上来就讲复杂网络而是先通过一个非常直观的例子来说明把图像划分成不同大小的网格然后在网格中心生成锚框。例如如果特征图是4 × 4说明图像被分成了 16 个位置如果特征图是2 × 2说明图像被分成了 4 个位置如果特征图是1 × 1说明整张图只有 1 个中心位置可以看到特征图越大位置越密适合检测小目标特征图越小位置越稀适合检测大目标这就是多尺度锚框的直觉来源。5. 用 4×4、2×2、1×1 特征图理解多尺度这是这一节最核心的理解方式。5.14 × 4特征图如果特征图大小为4 × 4那么说明有 16 个中心点可以生成锚框。这些中心点分布比较密集所以能够更细致地覆盖图像。因此它更适合检测小目标位置变化更细微的目标因为小目标本来就占据图像中的区域较小所以必须要有更密的采样位置。5.22 × 2特征图如果特征图大小为2 × 2那么只有 4 个中心点。相比4 × 4位置更稀疏但每个位置对应的感受范围更大。因此更适合检测中等偏大的目标。5.31 × 1特征图如果特征图大小为1 × 1那么整张图只有一个中心点。这时候生成的锚框基本就是围绕整张图的中心展开它更适合检测特别大的目标甚至接近整张图的目标。6. 多尺度锚框的代码思路李沐这里通常会写一个辅助函数用来在不同尺度特征图上显示锚框。核心思路是指定一个特征图大小例如fmap_w, fmap_h构造这个大小的随机张量调用d2l.multibox_prior把生成的锚框映射回原图上显示典型代码风格大致如下from d2l import torch as d2l import torch def display_anchors(fmap_w, fmap_h, s): fmap torch.zeros((1, 10, fmap_h, fmap_w)) anchors d2l.multibox_prior(fmap, sizess, ratios[1, 2, 0.5]) bbox_scale torch.tensor((w, h, w, h)) d2l.show_bboxes(d2l.plt.imshow(img).axes, anchors[0] * bbox_scale)这段代码的核心不是输入值本身而是只利用特征图的空间尺寸来决定锚框生成位置。7. 这段代码怎么理解7.1fmap torch.zeros((1, 10, fmap_h, fmap_w))这里构造一个张量形状是(批量大小, 通道数, 特征图高, 特征图宽)例如(1, 10, 4, 4)这里的数值内容不重要重要的是4 × 4这个空间大小。因为multibox_prior真正关心的是特征图有多高特征图有多宽它据此决定锚框中心的位置。7.2anchors d2l.multibox_prior(...)这一行负责在特征图每个位置生成锚框。假设特征图是4 × 4每个位置生成若干个锚框那么最终就会得到很多候选框。7.3bbox_scale torch.tensor((w, h, w, h))因为锚框坐标通常是归一化坐标范围相对于整张图。所以这里乘上原图的宽高把它还原成像素坐标方便画图显示。7.4d2l.show_bboxes(...)把生成出来的锚框画在原图上这样我们就能非常直观地看到4 × 4特征图生成的框更密集2 × 2特征图生成的框更稀疏1 × 1特征图生成的框覆盖范围最大8. 多尺度锚框的三个典型例子这一节博客里最好就按李沐常见的三个例子来讲。8.1 在4 × 4特征图上生成锚框例如display_anchors(fmap_w4, fmap_h4, s[0.15])这里的特点是中心点多锚框分布密锚框本身比较小所以更适合检测小目标。你可以把它理解为用更密的“探测器”去扫描图像中的细小区域。8.2 在2 × 2特征图上生成锚框例如display_anchors(fmap_w2, fmap_h2, s[0.4])这里的特点是中心点减少锚框分布更稀锚框尺度变大因此更适合检测中等大小目标。8.3 在1 × 1特征图上生成锚框例如display_anchors(fmap_w1, fmap_h1, s[0.8])这里的特点是整张图只有一个中心点锚框很大更适合覆盖大目标这种设置相当于在整张图的全局层面寻找大物体。9. 为什么大特征图适合小目标小特征图适合大目标这一点一定要在博客里讲透。9.1 大特征图适合小目标大特征图意味着位置采样更密每个单元对应原图中更小的区域更容易精确定位小物体因为小目标本来占的区域就少如果采样太稀很容易直接错过它。9.2 小特征图适合大目标小特征图意味着位置采样更稀每个单元对应更大的感受野更能概括大目标整体信息对于大目标来说不需要特别密集的采样因为它本身覆盖范围已经很大。10. 多尺度锚框和 SSD 的关系这一节其实就是在给 SSD 铺路。SSD 的核心思想之一就是在多个尺度的特征图上分别预测不同尺度的目标。也就是说前面较大的特征图负责小目标后面较小的特征图负责大目标而这些预测本质上就是在这些不同尺度特征图上生成锚框并对锚框进行分类与回归。所以可以说多尺度锚框是 SSD 的基础。如果这一节不懂后面学 SSD 时就会觉得它为什么要在那么多层上做预测很突兀。11. 多尺度锚框的本质理解这一节最核心的不是记住某个具体参数而是理解它背后的设计思想不同大小的目标应该交给不同尺度的特征图去处理。这其实体现了一种非常经典的深度学习视觉思想利用网络不同层的特征表示能力分工处理不同难度、不同尺度的问题。所以多尺度锚框不只是“多放几组框”而是一种结构化地组织检测任务的方法。12. 本节总结这一节我们学习了多尺度锚框核心内容可以总结为以下几点。12.1 为什么需要多尺度锚框因为真实图像中的目标大小差异很大单一尺度锚框难以同时覆盖小目标和大目标。12.2 多尺度锚框的核心思想在不同尺度的特征图上生成不同尺度的锚框用来检测不同大小的目标。12.3 大特征图和小特征图的分工大特征图位置更密适合小目标小特征图感受野更大适合大目标12.4 它是 SSD 的重要基础SSD 正是利用多尺度特征图和多尺度锚框来实现高效检测的。13. 学习感悟多尺度锚框这一节看起来不像 R-CNN、YOLO 那样“有名”但它其实非常关键。因为它第一次让我们真正意识到目标检测不是在单一层次上完成的而是需要结合不同层特征图的能力去共同处理不同尺度目标。这也是现代检测模型非常典型的设计思想。从这个角度看多尺度锚框其实不只是一个技巧而是对“检测任务如何分层解决”的一次非常清晰的表达。