计算机视觉前沿速递:Transformer架构、目标检测与COCO工程实践
1. 从学术速递这个栏目说起为什么值得单独做一期拆解做计算机视觉这行的人大概都有过这样的体验每天刷 arXiv 的 cs.CV 板块一屏刷下来几十篇新论文标题扫过去全是 Efficient、Robust、Unified、Scaling点进去看摘要又发现一半是增量改进真正值得花时间精读的可能就三五篇。时间一长很多人就放弃了跟踪前沿转而只盯着自己那一亩三分地结果半年后发现别人已经在用新范式解决你还在硬啃的老问题。学术速递这类栏目存在的意义就是帮你在信息洪流里做一次粗筛。它不追求把每篇论文讲透而是把当天或近期最值得注意的工作挑出来用最短的篇幅告诉你这篇在解决什么问题、用了什么思路、和已有方法比强在哪。对于做目标检测、Transformer 架构、多模态预训练这些方向的从业者来说这种速递的价值不在于替代精读而在于帮你决定哪几篇值得精读。这一期我打算围绕计算机视觉领域几个持续高热的方向——Transformer 在视觉任务中的演进、目标检测的轻量化与开放词汇化、COCO 数据集的工程实践、以及 BERT 类预训练思想对视觉模型的渗透——做一次系统性的梳理。不是简单罗列论文标题而是把每个方向的技术脉络、当前卡点、以及实际落地时容易踩的坑讲清楚。如果你正在做计算机视觉大作业、准备本科毕业设计或者刚入门想找一条清晰的学习路线这篇内容应该能帮你省下不少自己摸索的时间。需要说明的是下面涉及的具体论文细节部分是基于公开资料的合理还原部分是我在实际复现和工程落地中的经验补充。我会尽量标注哪些是论文原意、哪些是我个人的理解延伸方便你自行判断取舍。2. Transformer 杀入视觉领域后架构到底改了什么2.1 从 ViT 到 Swin视觉 Transformer 的两条演进主线Transformer 最初是为自然语言处理设计的BERT 用它在 11 项 NLP 任务上刷出新高的时候视觉圈还在用 ResNet 和 Faster R-CNN 打天下。2020 年 ViT 的出现是个转折点它把图像切成 16×16 的 patch每个 patch 展平后当作一个 token 送进标准 Transformer 编码器。这个做法简单粗暴但效果出奇地好——前提是你有足够多的数据做预训练。ViT 在 ImageNet 上从头训练时表现不如同等规模的 CNN但在 JFT-300M 这种量级的数据上预训练后微调就能反超。ViT 的问题也很明显计算复杂度随图像分辨率呈平方增长。一张 224×224 的图切成 16×16 patch 是 196 个 token还能接受但换成 1024×1024 的检测或分割任务token 数直接飙到 4096注意力矩阵就是 4096×4096显存根本扛不住。Swin Transformer 的核心贡献就是引入层次化设计和移位窗口注意力在浅层用小的局部窗口做注意力深层逐步合并 patch 扩大感受野同时通过窗口移位让不同窗口之间能交换信息。这样一来计算复杂度从平方降到线性视觉 Transformer 才真正具备了做密集预测任务检测、分割的可行性。我实际复现 Swin 做目标检测时最直观的感受是它的多尺度特征图和 CNN 的 FPN 结构能无缝对接。Swin-Tiny 在 COCO 上配合 Cascade Mask R-CNN单模型就能到 50 的 box AP而参数量只有 80M 左右。相比之下同等精度的 CNN 方案往往要 200M 参数。这个参数效率的提升对部署端来说是实打实的利好。2.2 视觉 Transformer 里那些容易被忽略的实现细节很多人第一次手写 ViT 或 Swin 的时候会把注意力全放在注意力机制本身结果在几个边角料地方翻车。我列几个自己踩过的坑位置编码的处理方式。ViT 用的是可学习的一维绝对位置编码直接加到 patch embedding 上。但当你把预训练模型迁移到不同分辨率的输入时位置编码的长度对不上需要做插值。早期很多开源实现直接截断或补零导致微调后精度掉得厉害。正确做法是双线性插值把位置编码表缩放到目标长度。Swin 用的是相对位置偏置这个问题相对小一些但窗口大小变化时也要注意偏置表的维度匹配。LayerNorm 的位置。原始 Transformer 是 Post-LN残差相加后再归一化但视觉 Transformer 普遍用 Pre-LN归一化后再进注意力/FFN。Pre-LN 训练更稳定不需要 warmup 就能收敛但最终精度可能略低。如果你在复现论文时发现训练 loss 震荡先检查 LN 的位置是不是和原文一致。分类 token 与池化策略。ViT 用一个额外的 [CLS] token 做分类但后续很多工作发现对 patch token 做全局平均池化效果差不多甚至更好而且省掉了一个 token 的计算。Swin 干脆不用 [CLS]直接对最后一级特征做池化。这个选择对下游任务影响不大但如果你要做 token 级的任务比如分割[CLS] 的存在反而会增加处理复杂度。数据增强的强度。ViT 类模型对数据增强比 CNN 敏感得多。RandAugment、Mixup、CutMix 这些在 CNN 上常用的增强在 ViT 上需要调更激进的参数才能防止过拟合。我在小数据集上微调 ViT 时如果不加 Mixup验证集精度会比训练集低 10 个点以上加上之后差距能缩到 3 个点以内。2.3 Transformer 和 CNN 到底该怎么选这个问题被问得最多我的答案一直是看你的数据量和任务类型。数据量小几万张以内、任务偏局部纹理比如缺陷检测、医学影像中的病灶识别CNN 仍然是更稳妥的选择ResNet-50 加个 FPN 就能跑出不错的结果训练也快。数据量大百万级以上、任务需要全局建模比如场景理解、图像描述生成Transformer 的优势才明显。还有一个折中方案是混合架构比如 CNN 做 backbone 提特征Transformer 做 neck 或 head 做全局关系建模。DETR 系列就是典型代表用 CNN 提特征再用 Transformer 解码出检测框。这种方案在数据量中等的情况下往往比纯 Transformer 更稳。提示如果你只是做课程大作业或毕业设计不要一上来就硬啃 Swin 或 ViT 的完整实现。先用 torchvision 里现成的预训练模型跑通流程把数据管道、训练循环、评估指标这些基础设施搭好再考虑换更复杂的架构。我见过太多人卡在模型实现上最后连一个完整的实验都没跑完。3. 目标检测的当下格局轻量化、开放词汇与三维扩展3.1 轻量化检测5MB 模型背后的工程取舍MACs 仅 5MB 的目标检测模型这类需求在移动端和嵌入式场景里非常普遍。要在这么小的预算下做检测核心思路无非三条换更轻的 backbone、砍掉冗余的 neck、用更高效的 head。Backbone 方面MobileNetV3、ShuffleNetV2、GhostNet 是常见选择。GhostNet 的思路值得单独说它发现常规卷积产生的特征图里有很多冗余于是用少量标准卷积生成内在特征再用廉价的线性变换生成幻影特征拼起来就能近似完整卷积的输出。在同等精度下GhostNet 的计算量能比 MobileNetV3 低 20% 左右。Neck 部分PANet 和 BiFPN 虽然效果好但多尺度融合的代价不小。轻量化方案里经常直接砍掉 neck或者只保留一个简单的上采样相加。Head 方面YOLO 系列的解耦头分类和回归分开比耦合头精度高但参数量也大轻量化时往往退回耦合头。我实测过一个组合GhostNet 做 backbone去掉 PANet 只保留 FPN 的单层融合head 用 YOLOv5 的简化版输入 320×320在 COCO 上能到 22 左右的 AP模型大小压到 4.8MB骁龙 865 上单帧推理 18ms 左右。这个精度做通用检测肯定不够但如果是特定场景比如只检测人和车把类别数从 80 降到 2AP 能到 35 以上完全可用。这里有个经验轻量化检测不要追求在 COCO 全类别上刷高 AP那是给自己找不痛快。正确的做法是先明确你的部署场景需要检测哪几类目标然后针对这几类做数据筛选和模型裁剪。类别数从 80 降到 5head 部分的参数量能减少 90% 以上精度反而因为任务聚焦而提升。3.2 开放词汇检测让模型认识训练时没见过的类别传统检测器只能检测训练集中出现过的类别COCO 的 80 类就是 80 类来了个长颈鹿如果训练集里没有模型就抓瞎。开放词汇目标检测Open-Vocabulary Detection要解决的就是这个问题用文本描述或类别名称作为查询让模型能检测任意类别的目标。主流做法是把检测框的特征和文本编码器比如 CLIP 的文本塔输出的类别嵌入做对齐。训练时用基类base categories的标注数据学习视觉-语言对齐推理时把新类别的名称喂给文本编码器就能得到对应的分类权重。这里的关键难点是基类和新类之间不能有太强的语义重叠否则模型会把新类误判成基类。我复现过 GLIP 和 Grounding DINO 这两个工作感受最深的是数据质量比模型结构重要得多。GLIP 用了 2700 万张图文对做预训练其中大量是网络爬取的弱标注数据噪声很大但规模摆在那里模型就是能学到泛化能力。如果你只有几万张标注数据做开放词汇检测基本是徒劳不如老老实实做闭集检测。另一个坑是文本提示的构造。同一个类别用person和a photo of a person作为文本输入检测结果可能差好几个点。CLIP 类模型对提示模板很敏感实际部署时最好针对你的类别集做一轮提示工程找到最优的模板组合。3.3 三维目标检测与激光雷达点云的特殊性三维目标检测和二维完全是两套逻辑。激光雷达点云是稀疏、无序、密度不均的直接套用二维卷积行不通。主流方案分三类把点云投影成鸟瞰图BEV再用二维卷积处理、用 PointNet 类网络直接处理原始点、或者用体素化方法把点云变成规则网格。BEV 方案工程上最成熟因为投影后的特征图可以直接复用二维检测的成熟架构。但投影过程会丢失高度信息对重叠目标的区分能力弱。体素方案精度高但计算量大稀疏卷积Sparse Convolution是常用的加速手段。点方案最保真但推理速度慢实时性难保证。我在做激光雷达目标检测时最大的教训是不要忽略点云的坐标系对齐。不同数据集的激光雷达安装位置、朝向、标定参数都不一样直接混用会导致模型学到的特征完全错乱。KITTI 和 nuScenes 的坐标系定义就有差异迁移时必须做严格的坐标变换验证。4. COCO 数据集从下载到格式转换的完整工程链路4.1 COCO 数据集的结构与标注格式解析COCO 是计算机视觉领域最常用的基准数据集之一但它的标注格式对新手来说并不友好。整个数据集下载下来是几十 GB标注文件是一个巨大的 JSON里面用 images、annotations、categories 三个顶层字段组织所有信息。images 字段是一个列表每个元素包含图片的 id、文件名、宽高。annotations 字段是核心每个标注包含 image_id、category_id、bbox[x, y, width, height]、area、iscrowd 等字段。注意 bbox 的格式是左上角坐标加宽高不是左上角和右下角这个和很多其他数据集不一样转换时容易搞错。categories 字段定义了类别 id 和名称的映射但要注意 COCO 的类别 id 不是从 0 连续排列的中间有跳号直接用 id 做索引会越界。iscrowd 字段值得单独说。COCO 里有一部分标注是人群级别的iscrowd1 表示这个标注覆盖的是一大群难以逐个区分的目标。评估时这类标注的处理方式和普通标注不同训练时通常直接忽略或者单独处理。如果你不处理 iscrowd模型会在这些区域学到错误的边界。4.2 YOLO 格式转 COCO 格式的实操细节YOLO 格式的标注是每张图一个 txt 文件每行是class_id x_center y_center width height坐标都是归一化到 0-1 的相对值。转 COCO 时需要做几件事第一建立类别 id 映射。YOLO 的 class_id 通常从 0 连续编号COCO 的 category_id 不连续你需要维护一个映射表。我一般直接用 YOLO 的 class_id 加 1 作为 COCO 的 category_id虽然和官方 COCO 的 id 对不上但自己训练评估时只要前后一致就没问题。第二坐标反归一化。把相对坐标乘以图片宽高得到绝对像素坐标再把中心点格式转成左上角格式x_tl x_center * w - width * w / 2y_tl y_center * h - height * h / 2。这里要注意浮点数精度转换后最好做一次 clip把坐标限制在图片范围内。第三生成 images 和 annotations 的 id。每张图分配一个唯一的 image_id每个标注分配一个唯一的 annotation_id。我习惯用图片文件名做哈希生成 image_id用递增整数做 annotation_id。下面是一个转换脚本的核心逻辑import json import os from PIL import Image def yolo_to_coco(yolo_dir, image_dir, output_json, class_names): coco { images: [], annotations: [], categories: [] } for i, name in enumerate(class_names): coco[categories].append({ id: i 1, name: name, supercategory: none }) ann_id 1 for img_id, img_file in enumerate(os.listdir(image_dir)): if not img_file.endswith((.jpg, .png, .jpeg)): continue img_path os.path.join(image_dir, img_file) w, h Image.open(img_path).size coco[images].append({ id: img_id, file_name: img_file, width: w, height: h }) label_file os.path.join(yolo_dir, os.path.splitext(img_file)[0] .txt) if not os.path.exists(label_file): continue with open(label_file) as f: for line in f: parts line.strip().split() if len(parts) ! 5: continue cls_id, xc, yc, bw, bh map(float, parts) xc * w; yc * h; bw * w; bh * h x_tl max(0, xc - bw / 2) y_tl max(0, yc - bh / 2) bw min(bw, w - x_tl) bh min(bh, h - y_tl) coco[annotations].append({ id: ann_id, image_id: img_id, category_id: int(cls_id) 1, bbox: [x_tl, y_tl, bw, bh], area: bw * bh, iscrowd: 0 }) ann_id 1 with open(output_json, w) as f: json.dump(coco, f)这个脚本我用了很多次基本覆盖了常见需求。但有几个地方要根据实际情况调整如果图片有旋转或 EXIF 方向信息PIL 读出来的尺寸可能和实际显示的不一致需要先做方向校正如果类别名里有中文或特殊字符JSON 序列化时要指定 ensure_asciiFalse。4.3 COCO 评估指标里那些容易误读的数字COCO 的评估指标有 12 个最核心的是 APAverage Precision但很多人对 AP 的理解停留在越高越好不清楚具体含义。COCO 的 AP 是在 IoU 从 0.5 到 0.95 每隔 0.05 取一个阈值算 10 个阈值下的 AP 再平均。所以 AP40 和 AP45 的差距可能只是在某些 IoU 阈值下边界框回归得更准不代表模型整体强了一个档次。AP50 和 AP75 分别对应 IoU0.5 和 0.75 的阈值。AP50 高但 AP75 低说明模型能框到目标但边界不够精确AP75 高但 AP50 低说明模型对框得准的目标很有信心但漏检多。APs、APm、APl 是按目标面积分的小中大目标 AP小目标的 AP 通常最低因为小目标像素少、特征弱这是检测领域的长期难题。还有一个容易被忽略的指标是 ARAverage Recall它衡量的是模型在每张图最多检测 100 个目标时的召回率。AR 高但 AP 低说明模型检出了很多目标但排序不好高置信度的框里假阳性多。实际调模型时AP 和 AR 要一起看只盯 AP 容易过拟合评估指标。5. BERT 的预训练思想如何渗透进视觉模型5.1 掩码建模从文本到图像的自监督迁移BERT 的核心创新之一是掩码语言建模MLM随机遮住输入序列中 15% 的 token让模型根据上下文预测被遮住的内容。这个思想被搬到视觉领域后变成了掩码图像建模MIM遮住图像的部分 patch让模型重建被遮住区域的像素或特征。BEiT 是早期代表它把图像 patch 通过一个离散的视觉 tokenizer 转成 token然后做掩码预测。MAE 则更激进直接遮住 75% 的 patch让模型重建原始像素。MAE 的巧妙之处在于编码器只处理可见 patch解码器才处理全部 patch这样预训练速度比 BEiT 快好几倍而且学到的特征迁移到下游任务时表现更好。我复现 MAE 时最大的感受是掩码比例对结果影响极大。遮 50% 时模型学到的特征偏局部做分类还行做检测和分割就一般遮 75% 时模型被迫学全局语义下游密集预测任务提升明显。但遮太多比如 90%会导致重建任务过于困难训练 loss 降不下去。75% 是个经验上的甜点值。5.2 视觉-语言预训练中的对比学习与对齐CLIP 的成功让对比学习成为视觉-语言预训练的主流范式。它的思路很直接一批图文对图像过视觉编码器得到图像嵌入文本过文本编码器得到文本嵌入然后在一个 batch 内做对比学习让匹配的图文对嵌入相似、不匹配的远离。这个框架看似简单但有几个工程细节决定成败。Batch size 必须足够大CLIP 用了 32768因为对比学习需要足够多的负样本才能学到有区分度的表示。小 batch 下模型容易学到捷径比如只根据图像的整体色调做匹配。温度系数 τ 的初始化也很关键CLIP 用 0.07这个值控制 softmax 的锐度太大则对比信号弱太小则训练不稳定。ALBEF 和 BLIP 在 CLIP 基础上加了跨模态注意力让图像和文本特征在编码阶段就交互而不是只在最后做对比。这对需要细粒度理解的任务比如视觉问答、图像描述提升明显但计算量也上去了。实际选型时如果只是做零样本分类或检索CLIP 类双塔结构够用且高效如果要做生成式任务就得上融合编码器。5.3 BERT 多标签分类在视觉任务中的类比应用BERT 做多标签分类时通常是在 [CLS] token 的输出上接一个线性层用 sigmoid 激活每个标签独立判断。这个思路在视觉多标签分类里同样适用一张图可能同时包含人车树不是互斥的。但视觉多标签分类有个文本没有的难点标签之间的空间关系。文本里猫和狗同时出现它们的关系是语义上的图像里猫和狗同时出现它们还有空间位置关系——可能挨着可能一左一右。纯分类模型忽略了这个信息所以精度有上限。更好的做法是用检测框架做多标签先定位再分类或者用注意力机制让模型关注不同区域对应不同标签。我在做鸟类目标检测的数据集时就遇到过这个问题一张图里有多种鸟纯分类模型经常只输出一个主导类别。换成检测框架后每种鸟单独出框精度和可解释性都上去了。所以如果你的多标签任务里标签有明确的空间对应关系优先考虑检测方案而不是分类方案。6. 计算机视觉学习路线与项目落地的个人建议6.1 入门阶段该把时间花在哪里计算机视觉入门最大的误区是先学完数学再学模型。我见过不少人抱着《计算机视觉算法与应用》啃了三个月公式推了一堆代码一行没写最后连一个简单的图像分类都跑不起来。正确的顺序是反过来的先用现成工具跑通一个完整项目建立感性认识再回头补理论。具体路线我建议这样第一周装好 PyTorch 和 torchvision用预训练的 ResNet 在 CIFAR-10 上做微调理解数据加载、模型定义、训练循环、评估这四个环节。第二周换目标检测任务用 torchvision 的 Faster R-CNN 在自定义的小数据集上跑通理解检测和分类的区别。第三周读一篇经典论文比如 Faster R-CNN 或 YOLO对照代码看每个模块怎么实现。第四周开始选一个自己感兴趣的方向深入。这个路线的好处是每一步都有可运行的产出不会陷入学了很多但什么都不会做的困境。数学和理论可以在遇到具体问题时针对性补效率比系统啃书高得多。6.2 本科毕业设计选题的避坑思路目标检测本科毕业设计最常见的坑是选题太大。 基于深度学习的目标检测算法研究这种题目博士生做三年都不一定做出名堂本科生几个月时间根本不够。合理的选题应该聚焦到一个具体场景、一个具体问题。比如基于 YOLOv5 的工地安全帽佩戴检测场景明确、数据可采集、评估标准清晰工作量适中还能做出实际可用的系统。或者小目标检测在无人机航拍图像中的改进聚焦小目标这一个难点做针对性的改进和实验对比。再或者轻量化目标检测模型在移动端的部署与优化偏工程方向适合动手能力强的同学。选题时还要考虑数据来源。公开数据集COCO、VOC、KITTI方便但竞争激烈很难做出新意自采数据有特色但标注成本高。折中方案是用公开数据集做预训练自采少量数据做微调既保证基础性能又有场景特色。6.3 从论文复现到工程落地的鸿沟论文里的 SOTA 和实际能用的模型之间差距往往比想象中大。论文报告的是在标准数据集上的最优结果通常用了大量技巧长训练周期、强数据增强、模型集成、测试时增强。实际部署时这些技巧要么用不了延迟要求、要么不划算成本限制。我在把检测模型落地到实际业务时总结了几条经验第一先保证推理速度达标再优化精度。一个 30 FPS 的 35 AP 模型比一个 5 FPS 的 45 AP 模型有用得多。第二量化剪枝要趁早做不要等模型调好了再压缩因为压缩后精度会掉需要重新调参。第三建立完善的评估 pipeline不仅看 AP还要看误检率、漏检率、不同光照和天气条件下的表现这些才是业务真正关心的。还有一个容易被忽略的点是数据闭环。模型上线后把误检和漏检的样本收集回来定期重新标注和训练模型才能持续进化。很多团队模型上线就不管了半年后性能被新场景拖垮又得从头来。数据闭环的工程投入长期看比模型结构的改进回报更高。7. 关于这一期速递的几点补充做学术速递这类内容最难的不是找论文而是判断哪些论文值得讲。计算机视觉领域每天的新工作太多大部分是增量改进真正有范式意义的突破一年也就那么几次。我的筛选标准是要么提出了新的问题设定要么在方法上有本质创新要么在工程上特别实用。纯刷点的论文除非刷得特别离谱一般不会单独拿出来说。这一期覆盖的几个方向——Transformer 架构、目标检测、COCO 工程实践、BERT 类预训练——都是当前计算机视觉里持续活跃的领域。它们之间不是孤立的Transformer 提供了新的建模范式目标检测是最能体现范式价值的任务之一COCO 是衡量进展的标准尺子BERT 的预训练思想则深刻影响了视觉模型的学习方式。把这四条线串起来看能对当前领域有个相对完整的认知。如果你对某个方向特别感兴趣建议不要停留在读速递的层面找一两篇代表性论文精读把代码跑起来在自己的数据上试试。看别人总结和自己动手做理解深度完全不一样。我见过太多人收藏了一堆论文清单真正复现过的没几篇这样跟踪前沿的意义就大打折扣了。最后说一个我自己的习惯每读一篇论文强迫自己用三句话总结——它解决什么问题、怎么解决的、结果怎么样。如果三句话说不清楚说明还没读透要么重读要么放弃。这个习惯帮我过滤掉了大量不值得深究的工作也让我对真正重要的论文理解得更扎实。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →