恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
DETR 端到端目标检测:Transformer 如何取消 Anchor 与 NMS
首页
资讯中心
/
DETR 端到端目标检测:Transformer 如何取消 Anchor 与 NMS
DETR 端到端目标检测:Transformer 如何取消 Anchor 与 NMS
发布时间:2026/10/15 10:25:57
简介这套PPT是围绕计算机视觉经典论文 DETRDEtection TRansformer整理的文献汇报课件适合需要做组会分享的研究生、目标检测方向初学者及相关从业者。内容从研究背景展开先对比RCNN系列和YOLO系列依赖 Anchor、NMS 等手工组件的传统检测流程再引入 DETR 将目标检测视为直接集预测的核心思想课件详细拆解了 CNN 特征提取、Transformer 编码器-解码器、Object Queries、二分图匹配损失与 FFN 预测等关键环节也说明了模型可扩展到全景分割任务的应用价值。资源共1个文件文件类型为 pptx压缩包大小约3.44MB精炼完整适合直接作为组会汇报底稿或论文阅读笔记。目前已有1089人学习/浏览。通过学习该课件可以系统理解 DETR 的端到端检测思路和训练机制同时节省整理原论文图表与公式的时间为后续研究 Transformer 在视觉任务中的应用打下基础。1. 这篇 End-to-End Object Detection with Transformers 论文汇报把机器学习里 DETR 最反直觉的一件事讲清楚了目标检测不一定非要从一张图上铺满先验框开始。这篇 End-to-End Object Detection with Transformers 文献汇报核心只讲了一件事DETR 怎么把检测当成集合预测问题直接从输入到输出端到端地给出框和类别彻底绕开 Anchor 设计、NMS 这种手工组件。汇报按研究背景、研究目的、研究过程、结论四段展开每一段都对应原论文的关键章节读完既能向别人解释 DETR 为什么能省掉那些模块也能按图索骥进入复现流程。它适合准备组会分享的研究生、刚接触检测方向的新手也适合从 YOLO 或 Faster R-CNN 迁移过来、想搞清楚 Transformer 派对检测管线到底动了什么的人。这份材料的价值在于把模型结构、训练匹配、损失设计和实验消融连成了一条完整线索而不是把论文贴一遍。2. 架构三件套CNN 特征压缩、Transformer 编解码与 FFN 预测头的配合逻辑DETR 的模型结构拆开看只有三部分CNN backbone、Transformer encoder-decoder、FFN 预测头。很多人第一眼只记住「用了 Transformer」但真正决定能不能复现的是 CNN 和 Transformer 之间的数据接口——一张图怎么变成序列、序列长度是多少、通道数压到多少、位置信息靠什么补上。这一章就把这条链路一步步拆开。2.1 为什么还要 CNN从 2048 通道特征图到序列化的第一步先回答一个常见疑问既然要做端到端为什么不直接让 Transformer 吃原始像素因为自注意力的计算量随 token 数量平方增长原图 800×600 就有 48 万个像素两两做 attention 在工程上完全跑不动。CNN 的作用是把空间尺寸压下来常见主干网络输出特征图相对原图缩小 32 倍800×600 的输入到这里变成 25×19 左右的空间分辨率token 数量从几十万降到几百Transformer 才算得动。同时主干网络输出 2048 个通道每个通道提取了不同的图像特征。但 Transformer 期望输入是序列所以要先把四维特征图转成二维矩阵。常见做法是先用 1×1 卷积把通道从 2048 压缩到 d再把高和宽合并成一个维度。下面这段代码就是这个桥接过程的 PyTorch 示意import torch import torch.nn as nn class BackboneToSequence(nn.Module): def __init__(self, in_channels2048, d_model256): super().__init__() # 1x1 卷积只做通道混合不改变空间尺寸 self.proj nn.Conv2d(in_channels, d_model, kernel_size1) def forward(self, feat: torch.Tensor): # feat: (B, 2048, H, W) 来自 CNN backbone B, C, H, W feat.shape x self.proj(feat) # (B, 256, H, W) x x.flatten(2) # (B, 256, H*W) x x.permute(2, 0, 1) # (H*W, B, 256) return x这里的 flatten(2) 把空间维度 H 和 W 合并成一个 HW 维顺序是先沿 W 再沿 H 展开后边加位置编码时要保持这个顺序和原始特征图坐标一一对应。permute 把序列长度放到第一维是为了贴合 Transformer 常用的 seq_len, batch, d_model 布局。d_model 取 256 是原论文比较常用的配置显存紧张时也可以降到 192但 encoder 输出维度会随之变小最终 AP 会略掉一些。1×1 卷积在这里不做残差、不加激活只是纯粹的通道压缩。2.2 Encoder全局自注意力如何替代滑动窗口先验Encoder 接收的是加了位置编码的序列。位置编码是必须的因为 reshape 之后特征图的排列顺序包含空间位置信息但自注意力本身是顺序无关的如果不把位置信息显式告诉模型它会把左上角和右下角的特征当成完全等价的 token。常见做法是加正弦位置编码也有用可学习位置编码的版本。DETR 里位置编码不只是加在最前面还会在 encoder 每一层的注意力输入里补充一次让每一层都能感知空间关系。有了位置编码以后encoder 内部每个 token 都会和整张特征图的所有 token 计算注意力权重。这一步就是「全局建模」某个位置的像素可以直接看到远处另一个目标的像素而不需要靠滑动窗口一步步扫过去。滑动窗口的问题是感受野受限先验框只能覆盖局部目标之间、目标与背景之间的长程依赖很难在一次前向中建立而全局自注意力相当于把整幅图的所有位置两两建边实例之间的区分信息在 encoder 阶段就完成了。这也是 DETR 能去掉 Anchor 的底层原因——Anchor 本质上是用密集先验去覆盖目标可能出现的位置而 Transformer 用全局 attention 直接建立「这个位置和那个位置是不是属于同一个目标」的关系。2.3 Decoderobject queries 并行解码与 FFN 输出的固定 N 个预测Decoder 和标准 Transformer decoder 的差别在于DETR 在每个解码层并行解码 N 个目标不是自回归式逐个生成。N 在论文里通常取 100意思是模型最多预测一张图中的 100 个目标。object queries 是 N 个随机初始化然后训练出来的向量每个 query 通过训练学到一种「职责」有的负责询问图像左下角区域有的负责中间区域。它们在 decoder 中和 encoder 输出的特征做 cross-attention并在 N 个 query 之间做 self-attention从而让模型在整图上下文里统一推理所有目标。import torch.nn as nn num_queries 100 # N最大预测目标数 d_model 256 # object queries 是可学习参数不是人为设计的先验框 object_queries nn.Parameter(torch.randn(num_queries, d_model)) # 每个 batch 的输入 shape 都是 (num_queries, batch, d_model) tgt object_queries.unsqueeze(1).repeat(1, batch_size, 1)object_queries 初始值是随机噪声训练后每个向量学会去「询问」图像中某类区域。tgt 在 decoder 里作为第一层注意力输入的 query 侧encoder 的输出作为 key 和 value 侧。这里最需要注意的是这些 queries 不是 Anchor它们不含有预设的宽高比或位置偏移所有框信息都是在 decoder 的 cross-attention 中从图像特征里取出来的。每个 query 经过 decoder 后得到一个输出 embedding再送入 FFN 预测头。FFN 由三层组成一个 ReLU 激活层、一个 d 维隐藏层、一个线性投影层。线性层输出类别概率和框坐标框坐标是标准化后的中心点位置和宽高。由于 N100 远大于图像中实际目标数量FFN 还需要预测一个特殊类 ∅表示这个槽位没有检测到对象效果类似传统检测里的 background 类。3. 训练内核二分匹配、匈牙利算法与组合损失推理时 DETR 一次前向就输出 N 个预测框但训练时不能直接拿这 N 个框去和 GT 算 loss——因为模型不知道第一个框对应的是图像里的哪只猫也不知道剩下那些「空槽位」该匹配谁。所以训练和推理之间横着一个关键步骤先用二分匹配把预测和 GT 一一对应再算损失。3.1 固定 N 个预测与动态数量 GT 怎么对齐DETR 的预测集合固定大小是 N但每张图的 GT 数量是变化的比如一张图只有 3 个目标另一张图有 20 个。为了让两个集合能比较训练时要先把 GT 补齐到 N真实目标维持原类别和框坐标不足的部分用 ∅ 类别填充。这样预测集合和 GT 集合大小都是 N可以做一对一的整体匹配。这里有一个很多复现者第一次没绕过来的点匹配是全局最优匹配不是每个预测单独找最近 GT。如果让每个预测各自贪心地找最近的 GT可能出现多个预测同时匹配到同一个目标、而另一个目标没人认领的情况。DETR 用二分图匹配保证每个预测恰好匹配一个 GT每个 GT 恰好匹配一个预测目标是让整体匹配代价最小。二分匹配只在训练阶段使用推理时没有匹配过程直接取每个预测的类别概率和框坐标输出。这也是设计上比传统检测「先出大量候选框再做 NMS」更简洁的地方训练时通过匹配让模型学会每个 query 该负责哪个目标推理时也就不需要后处理来剔除重复框。3.2 匈牙利算法代价矩阵怎么构造、为什么 GT 也要补齐到 N求解二分图匹配的经典工具是匈牙利算法Python 里可以直接用 scipy 的 linear_sum_assignment。关键难点在代价矩阵的构造矩阵行对应 N 个预测列对应 N 个 GT每个元素是「预测 i 匹配 GT j 的代价」。代价由两部分组成类别预测的负对数似然以及框坐标的 L1 距离与 GIoU 距离。import numpy as np from scipy.optimize import linear_sum_assignment # 假设 num_pred100, num_gt100GT 已补 ∅ 到同样长度 # cost_matrix[i, j]预测 i 匹配 GT j 的综合代价越小越好 cost_matrix np.zeros((100, 100)) cost_matrix cls_cost box_cost # 两者都已经是 (100, 100) pred_idx, gt_idx linear_sum_assignment(cost_matrix) # pred_idx 与 gt_idx 一一对应即最优匹配结果scipy 返回的 linear_sum_assignment 会把行索引和列索引分别返回一一对应就是最优匹配。需要注意这两个索引等长且行和列各自不重复。构造代价矩阵时如果 GT 没补齐到 N矩阵就会变成 100×3 这种非方阵匈牙利算法虽然能跑但含义变成「只为部分 GT 分配预测」剩下的预测既没有匹配目标也没有 ∅ 惩罚训练就会失去对空槽位的约束。3.3 三类损失组合分类负对数似然、L1 与 GIoU 的比例匹配完成之后损失就按匹配对来计算。整体损失分三块分类损失用负对数似然匹配到 ∅ 的预测作为 background 类计算框坐标损失用 L1另外还叠加一个 GIoU 损失。L1 直接计算中心点坐标和宽高的绝对差但对小目标天然不公平——同样 5 个像素的偏差在一个 30×30 的小框上相对误差很大在一个 300×300 的大框上却可以忽略。GIoU 衡量的是两个框的重合程度对目标尺度不敏感两者互补。复现时通常按这种起始配置loss cls_loss 5.0 * l1_loss 2.0 * giou_lossL1 权重取 5、GIoU 权重取 2 是常见起步值原因是 GIoU 本身数值范围在 [-1, 1] 附近而 L1 的绝对数值通常更小不加权重容易让 L1 在总损失里占比过低。如果小目标检测效果差优先调大 giou_weight如果类别错分明显优先调大 cls_loss 权重。消融实验也证明了纯 L1 的效果很差和 GIoU 结合后中目标和大目标的 AP 改善最明显。4. 实验设计怎么读与 Faster R-CNN 对齐和四组关键消融汇报的实验部分给出了五组信息COCO 上与 Faster R-CNN 的综合对比、encoder 层数影响、decoder 层数影响、位置编码消融、loss 消融外加一个全景分割扩展。这五组实验不是平行罗列而是层层递进地回答三个问题性能到底行不行、哪个组件贡献最大、模型是不是只适合检测任务。4.1 COCO 对标 Faster R-CNN性能相当训练成本不可忽略在 COCO 数据集上DETR 的准确率和检测速度和 Faster R-CNN 基本相当。这里要特别注意的是训练成本DETR 的完整训练通常需要跑到 500 epoch 左右而 Faster R-CNN 在标准设置下往往几十个 epoch 就能收敛。很多人在复现时只看到「性能相当」就以为可以直接替换实际落地时如果用同样算力DETR 的训练时间会是 Faster R-CNN 的好几倍。汇报里说「准确性和检测速度性能相当」是有前提的——它建立在足够长的训练之上。这个点在做技术选型时比模型结构本身更值得关注。4.2 encoder 层数、decoder 层数与 NMS 叠加的三组观察汇报里最容易被复现者直接参考的是三组消融观察实验变量汇报中观察到的趋势复现时需要盯住的点encoder 层数增加AP 逐步提升更多 encoder 层带来更精细的全局建模encoder 从 3 层加到 6 层时收益最明显超过 6 层后训练显存压力增大decoder 层数增加每一层后 AP 和 AP50 都有提升decoder 深度直接决定集合预测的精度减到 3 层以下掉点明显在 decoder 输出叠加 NMS没有一致增益DETR 设计上不需要 NMS如果加了 NMS 发现掉点说明是重复框误删不是参数问题encoder 层数的提升逻辑很直观更多层意味着更充分的全局信息交换实例分离得更干净。decoder 每一层的提升则说明集合预测不是一步到位而是逐层精化前几层把目标大致分开后几层逐步细化框的位置和类别。NMS 那组实验是很多人容易忽略的设计佐证——传统检测器需要 NMS 是因为候选框之间互相不知道对方的存在而 DETR 的 decoder 通过 self-attention 让所有 predictions 两两可见重复框的抑制是在模型内部学习出来的不需要外部手工规则。4.3 位置编码与 loss 消融以及全景分割的一个小扩展位置编码消融是四组实验里信号最强的一组去掉空间位置编码和输出位置编码后AP 显著下降。这说明 Transformer 在目标检测里不能只依赖 CNN 特征的空间排列必须显式把位置信息喂进去。复现时常见错误是把位置编码只加在 encoder 输入decoder 侧的 object queries 完全不带位置信息结果模型很难定位目标。loss 消融的结论前面已经提过只用 L1 效果差加 GIoU 后中目标和大目标 AP 改善明显。这组实验验证了组合损失的必要性也给参数调优指了方向。全景分割是 DETR 的迁移验证在固定 DETR 模型的基础上只训练一个小的扩展分支就能做全景分割效果不错。这里的关键词是「固定」——目标检测训练好的 encoder-decoder 权重没有重新训练说明模型学到的目标级表示是可迁移的不是只对框回归有效。这个结论对想拿 DETR 做多任务的人很有参考价值先训练检测再挂轻量头做分割比从头训练一个多任务模型省很多成本。5. 避坑与常见问题复现 DETR 与准备汇报时容易翻车的五个点DETR 的复现难度不在于网络结构本身而在于训练管线里几个小细节。这些坑我基本都踩过每条按现象、原因、解决的方式列出来可以当作复现时的自查清单。5.1 训练时 GT 补齐到 N 维度对不上匈牙利算法直接报错现象构造代价矩阵时 shape 对不上报错提示 broadcasting error 或者 linear_sum_assignment 返回值长度不一致。原因是 GT 集合没有补齐到 N代价矩阵变成非方阵匹配结果语义完全错误。解决方法是训练数据处理时就把 GT 补齐真实目标保留类别和框坐标其余位置类别置为 ∅框坐标置零同时在损失计算时记录一个 mask只对有效位置计算框损失避免补齐的零框干扰 GIoU。检查形状是最快的验证方式cost_matrix 一定是 N×Npred_idx 和 gt_idx 长度都是 N。5.2 在 DETR 输出上加 NMS反而掉点现象把原有检测流程里的 NMS 后处理加到 DETR 输出上AP 不升反降。原因是 DETR 的 decoder 已经通过 query 之间的 self-attention 抑制了重复预测模型内部已经做了类似 NMS 的工作再加手工 NMS 会把那些置信度略低但确实是正确目标的框误删掉。解决方法是直接去掉 NMS。如果发现输出里出现明显重复框先检查训练是否收敛、object queries 数量是否充足而不是急着加后处理模块。5.3 位置编码加错位置或漏加AP 明显下滑现象训练到一定阶段后验证集 AP 上不去或者比同配置的参考结果低 10 个点以上。原因是位置编码没有加到每层注意力的 query 和 key 上或者干脆只在 encoder 输入端加了一次。位置编码的目的是让注意力层知道 token 之间的空间关系如果它只参与 value 计算而不影响 query-key 的相似度注意力权重就仍然是空间无关的。解决方法是检查每个 encoder layer 的 self-attention位置编码需要叠加在 query 和 key 的输入上而不是只加在 token embedding 上。常见实现里位置编码是一个独立的 tensor在每个注意力层前分别加到 q 和 k 上。5.4 把 object queries 当作 Anchor 来调参现象复现时想当然去调整 query 的数量和初始化方式甚至有人按 Anchor 的思路给不同 query 设置不同的宽高比预期结果训练曲线乱七八糟。原因是 object queries 和 Anchor 本质不同Anchor 是预设的、固定的一组先验框而 object queries 是随机初始化后从数据里学出来的「提问向量」它们不对应任何具体的框形状。解决方法是把 object queries 当成参数而不是先验保持随机初始化通过训练让它自己学出分工。想观察每个 query 学到了什么可以直接可视化 decoder attention map你会看到不同 query 集中关注图像的不同区域而不是不同宽高比的框。5.5 DETR 收敛慢被误判为训练失败现象训练到 150 epoch 时 AP 还没赶上 Faster R-CNN以为模型坏了提前停掉。原因是 DETR 的二分匹配在训练早期不稳定匹配关系会随网络参数变化而跳变模型需要很长时间才能把匹配和特征学习协调好。500 epoch 是常见完整配置300 epoch 只能算快速验证。解决方法是先跑一个 300 epoch 的小规模验证观察验证集 AP 是否持续上升且没有明显震荡如果曲线确实在涨说明管线是对的再拉长到 500 epoch。训练时常见配置是两个学习率主网络用 1e-4backbone 用 1e-5配合 warmup 300 步损失通常会在前几十个 epoch 波动较大这是匹配跳变的正常现象。6. 把汇报 PPT 变成自己的复现清单六个问题检验是否吃透 DETR拿到这份汇报之后我通常不只是读一遍而是把它当成一张自测卷。每一页 PPT 对应一个「不看原论文能不能讲清楚」的问题。我自己的做法是把汇报四个部分转成六个提问逼自己不看材料现场作答汇报部分应该能回答的问题研究背景Anchor 和 NMS 为什么是手工组件DETR 靠什么取消了它们研究目的集合预测和「先出候选框再后处理」的代理任务差异在哪研究过程CNN 输出通道数是多少、空间尺寸缩小多少倍、Transformer 输入 shape 是什么研究过程代价矩阵是多少乘多少GT 怎么补 ∅匈牙利算法的输入输出分别是什么研究过程三部分损失各解决什么问题起始权重怎么设实验哪组消融最能说明位置编码的必要性NMS 叠加为什么没有收益六个问题答完对 DETR 的理解基本就达到能复现的层次。也可以做一个更硬核的验证把代价矩阵和匈牙利算法单独摘出来跑一个 5 行的小脚本确认维度处理正确import numpy as np from scipy.optimize import linear_sum_assignment cost np.zeros((100, 100)) # 预测 100GT 补 ∅ 到 100 cost[:3, :3] -2.0 # 前 3 个真实目标附近给低代价 row, col linear_sum_assignment(cost) assert len(row) len(col) 100 # 维度必须严格对齐这个脚本跑通说明你对方阵匹配、补齐逻辑、索引对应关系都有了实际手感而不是停留在 PPT 的文字描述里。从那以后我每次拿到论文汇报 PPT都强制先过一遍「提问 → 作答 → 找证据」这个流程答不上来的地方回到原论文对应章节重读而不是急着复现代码。这样做最大的好处是复现时遇到问题能快速定位是模型结构的问题还是数据管线的问题少走很多弯路。希望这份资源的拆解和这套提问方式也能帮到你。本文还有配套的精品资源点击获取