单阶段 vs 双阶段目标检测:从候选集合到 NMS 的工程算账
从工程视角系统对比 one-stage 与 two-stage 检测:把它们统一成‘生成候选→打分→去重’的流程,然后用可复制的数字(anchors 数量、top-k、NMS 最坏复杂度)解释速度差异,并用 focal loss vs 采样策略解释训练差异。文末提供纯 NumPy 可运行的 NMS 与候选规模算账代码,帮助你做选型与排查。
从工程视角系统对比 one-stage 与 two-stage 检测:把它们统一成‘生成候选→打分→去重’的流程,然后用可复制的数字(anchors 数量、top-k、NMS 最坏复杂度)解释速度差异,并用 focal loss vs 采样策略解释训练差异。文末提供纯 NumPy 可运行的 NMS 与候选规模算账代码,帮助你做选型与排查。
副标题 / 摘要 Anchor-based 依赖预设锚框,Anchor-free 直接预测中心或边界。本文用 ACERS 框架对比两条路线的原理、优缺点与工程实践。 预计阅读时长:15~18 分钟 标签:object-detection、anchor-based、anchor-free SEO 关键词:Anchor-Based, Anchor-Free, 目标检测 元描述:系统对比 anchor-based 与 anchor-free 的核心差异与工程取舍。 目标读者 想理解检测框架差异的初学者 需要做检测模型选型的工程实践者 关注推理速度与精度权衡的开发者 背景 / 动机 目标检测发展出了两条主路线: 一条是预设锚框(anchor-based),一条是直接预测(anchor-free)。 理解它们的本质差异,有助于工程选型与调参策略。 核心概念 Anchor:预设的候选框模板。 Anchor-based:预测 anchor 的偏移与类别。 Anchor-free:直接预测中心点/边界或关键点。 正负样本分配:训练时匹配策略不同。 A — Algorithm(题目与算法) 用通俗语言说明主题内容 Anchor-based:先铺满锚框,再回归偏移。 Anchor-free:不需要锚框,直接预测目标位置。 基础示例(1) Faster R-CNN/YOLOv2:典型 anchor-based。 基础示例(2) FCOS/CenterNet:典型 anchor-free。 实践指南 / 步骤 数据集目标尺度多样 → anchor-based 更稳。 追求简化后处理 → anchor-free 更简洁。 先做小规模对比实验,再决定路线。 可运行示例(最小框编码示意) import torch # anchor-based: 预测偏移 anchor = torch.tensor([10.0, 10.0, 50.0, 50.0]) target = torch.tensor([12.0, 14.0, 52.0, 56.0]) delta = target - anchor print(delta) # anchor-free: 直接预测中心与宽高 center = torch.tensor([(target[0]+target[2])/2, (target[1]+target[3])/2]) wh = torch.tensor([target[2]-target[0], target[3]-target[1]]) print(center, wh) 解释与原理 Anchor-based 需要精心设计 anchor 尺度与比例。 Anchor-free 省掉 anchor 设计,但依赖中心点分配策略。 C — Concepts(核心思想) 方法类型 Anchor-based 与 anchor-free 都属于密集检测框架,差异在于候选框设计。 ...
副标题 / 摘要 IoU(Intersection over Union)衡量两个边界框的重叠程度,是目标检测评估的核心指标。本文用 ACERS 框架拆解公式、计算步骤与工程应用。 预计阅读时长:12~16 分钟 标签:iou、object-detection、bbox SEO 关键词:IoU, 交并比, 目标检测, BBox 元描述:讲清 IoU 的计算方法、阈值含义与工程实践。 目标读者 想快速理解 IoU 公式与计算的入门读者 需要调试检测指标的工程实践者 关注视觉评估标准的开发者 背景 / 动机 目标检测不仅要“找对类别”,还要“框得准确”。 IoU 是衡量框是否准确的标准指标,直接影响 AP、mAP 等评估结果。 理解 IoU 的定义与阈值意义,是检测工程的基本功。 核心概念 BBox(边界框):用 (x1, y1, x2, y2) 表示左上与右下坐标。 交集面积:两个框重叠部分的面积。 并集面积:两个框面积之和减去交集。 A — Algorithm(题目与算法) 用通俗语言说明主题内容 IoU 就是“重叠面积 / 总面积”。 重叠越大,IoU 越接近 1;完全不相交则为 0。 基础示例(1) 框 A:[(0,0),(2,2)] 框 B:[(1,1),(3,3)] 交集面积 = 1,A 面积 = 4,B 面积 = 4 → IoU = 1 / (4 + 4 - 1) = 1/7。 基础示例(2) IoU ≥ 0.5 → 常视为检测正确(TP)。 IoU ≥ 0.75 → 更严格的高质量检测。 实践指南 / 步骤 计算交集框坐标。 得到交集面积。 计算两框面积。 交并比 = 交集 / 并集。 可运行示例(最小 IoU 计算) def iou(box1, box2): x1 = max(box1[0], box2[0]) y1 = max(box1[1], box2[1]) x2 = min(box1[2], box2[2]) y2 = min(box1[3], box2[3]) inter_w = max(0, x2 - x1) inter_h = max(0, y2 - y1) inter = inter_w * inter_h area1 = (box1[2] - box1[0]) * (box1[3] - box1[1]) area2 = (box2[2] - box2[0]) * (box2[3] - box2[1]) union = area1 + area2 - inter return inter / union if union > 0 else 0.0 box_a = (0, 0, 2, 2) box_b = (1, 1, 3, 3) print(iou(box_a, box_b)) 解释与原理 IoU 是一个归一化指标,与尺度无关。 交集为 0 时,IoU 为 0。 在训练时常用 IoU 作为正负样本匹配标准。 C — Concepts(核心思想) 方法类型 IoU 属于几何评估指标,用于衡量两个区域的重叠程度。 ...
副标题 / 摘要 空洞卷积通过插入“空洞”扩大感受野,在不显著增加参数的情况下捕获长距离上下文。本文按 ACERS 结构解析原理、复杂度与工程场景,并提供最小可运行示例。 预计阅读时长:14~18 分钟 标签:dilated-convolution、segmentation、vision SEO 关键词:空洞卷积, Dilated Convolution, Atrous 元描述:解释空洞卷积的原理、复杂度与工程应用,含最小示例。 目标读者 想理解感受野扩大策略的入门读者 从事语义分割、时序建模的工程实践者 需要在算力与效果间权衡的开发者 背景 / 动机 传统卷积增大感受野通常靠加深网络或增大核尺寸,但这会带来更多参数与计算。 空洞卷积用“稀疏采样”的方式扩大感受野,是更高效的替代方案。 核心概念 空洞率(dilation):卷积核元素之间的间隔。 感受野:输出特征与输入区域的覆盖范围。 稀疏采样:在输入上跳步取样。 A — Algorithm(题目与算法) 用通俗语言说明主题内容 空洞卷积就是“把卷积核撑开”,让核的元素之间有空洞,从而覆盖更大的输入范围。 基础示例(1) 3x3 卷积,dilation=2 → 覆盖 5x5 的感受野。 基础示例(2) 不增加参数数量,但能捕捉更大上下文。 实践指南 / 步骤 选择基础卷积核(如 3x3)。 设置 dilation(常用 2、4、8)。 观察感受野与特征分辨率变化。 避免过大 dilation 导致“栅格效应”。 可运行示例(最小 PyTorch 空洞卷积) import torch import torch.nn as nn x = torch.randn(1, 3, 32, 32) conv = nn.Conv2d(3, 8, kernel_size=3, dilation=2, padding=2) out = conv(x) print(out.shape) 解释与原理 有效感受野:k_eff = k + (k-1) * (d-1)。 参数量与标准卷积相同,计算量近似不变。 C — Concepts(核心思想) 方法类型 空洞卷积属于扩大感受野的卷积变体,常用于分割与时序模型。 ...
副标题 / 摘要 NMS(Non-Maximum Suppression)是目标检测后处理的核心步骤。本文用 ACERS 框架拆解 NMS 的原理、流程与工程实践,并提供可运行的 PyTorch 示例。 预计阅读时长:14~18 分钟 标签:nms、object-detection、iou SEO 关键词:NMS, 非极大值抑制, IoU, 目标检测 元描述:讲清 NMS 的核心算法、复杂度与工程取舍。 目标读者 想理解目标检测后处理的初学者 需要调参 IoU 阈值的工程实践者 关注推理速度与精度平衡的开发者 背景 / 动机 检测模型通常会输出多个重叠框。 如果不做抑制,会出现“同一目标被重复检测”。 NMS 用最简单的规则实现去重,是工业界的标准方案。 核心概念 IoU(Intersection over Union):衡量两个框重叠程度。 score:置信度分数,决定优先保留的框。 阈值:IoU 超过阈值则抑制。 A — Algorithm(题目与算法) 用通俗语言说明主题内容 NMS 的逻辑很直观: 选出最高分的框。 删除与它重叠度过高的框。 重复直到没有框。 基础示例(1) 两个高度重叠的人脸框,只保留分数更高的一个。 基础示例(2) 多个类别的检测结果,先按类别分开再做 NMS(class-wise)。 实践指南 / 步骤 对检测框按 score 排序。 取最高分框作为保留结果。 计算 IoU,过滤高重叠框。 重复直到框集合为空。 可运行示例(最小 PyTorch NMS) import torch def iou(box, boxes): x1 = torch.maximum(box[0], boxes[:, 0]) y1 = torch.maximum(box[1], boxes[:, 1]) x2 = torch.minimum(box[2], boxes[:, 2]) y2 = torch.minimum(box[3], boxes[:, 3]) inter = torch.clamp(x2 - x1, min=0) * torch.clamp(y2 - y1, min=0) area1 = (box[2] - box[0]) * (box[3] - box[1]) area2 = (boxes[:, 2] - boxes[:, 0]) * (boxes[:, 3] - boxes[:, 1]) union = area1 + area2 - inter return inter / (union + 1e-6) def nms(boxes, scores, thresh=0.5): idx = scores.argsort(descending=True) keep = [] while idx.numel() > 0: i = idx[0] keep.append(i.item()) if idx.numel() == 1: break rest = idx[1:] ious = iou(boxes[i], boxes[rest]) idx = rest[ious <= thresh] return keep boxes = torch.tensor([ [0.0, 0.0, 1.0, 1.0], [0.1, 0.1, 1.1, 1.1], [2.0, 2.0, 3.0, 3.0], ]) scores = torch.tensor([0.9, 0.8, 0.7]) print(nms(boxes, scores, thresh=0.5)) 解释与原理 NMS 的核心是“先保留最可信框”。 IoU 阈值越大,保留框越多;越小,抑制越强。 C — Concepts(核心思想) 方法类型 NMS 属于后处理过滤算法,用局部贪心策略去重。 ...
副标题 / 摘要 CNN 的参数量取决于卷积核大小、通道数与偏置项。本文用 ACERS 框架给出计算公式、示例与工程实践,帮助你快速评估模型规模。 预计阅读时长:12~16 分钟 标签:cnn、parameter-count、convolution SEO 关键词:CNN, 参数量, 卷积, 模型大小 元描述:讲清 CNN 参数量的计算公式与工程取舍。 目标读者 想快速估算模型规模的初学者 关注部署成本与显存预算的工程实践者 需要做模型压缩与设计取舍的开发者 背景 / 动机 模型参数量直接影响训练速度、推理成本与部署体积。 对于 CNN,参数量可精确计算,但容易被忽略或算错。 掌握计算方法是做结构设计与成本评估的基础。 核心概念 卷积核参数量:核高 * 核宽 * 输入通道 * 输出通道。 偏置项:每个输出通道一个偏置。 组卷积:参数量随 groups 减少。 A — Algorithm(题目与算法) 用通俗语言说明主题内容 CNN 参数量的核心是: “每个输出通道有一组卷积核,核大小覆盖所有输入通道”。 基础示例(1) 卷积:3x3, in=3, out=64 参数量:333*64 + 64 = 1,792 基础示例(2) 1x1 卷积:in=256, out=128 参数量:11256*128 + 128 = 32,896 实践指南 / 步骤 明确卷积核大小 (KxK)。 确认输入通道数 C_in 与输出通道数 C_out。 计算参数量:K*K*C_in*C_out + C_out。 若是组卷积,再除以 groups。 可运行示例(最小 PyTorch 计算) import torch import torch.nn as nn conv = nn.Conv2d(3, 64, kernel_size=3, bias=True) params = sum(p.numel() for p in conv.parameters()) print(params) # 1792 解释与原理 卷积层参数量与输入图像大小无关,只与核与通道有关。 1x1 卷积参数量依然可能很大,因为通道数通常很高。 C — Concepts(核心思想) 方法类型 CNN 参数量计算属于模型规模评估方法,用于衡量存储与计算成本。 ...
副标题 / 摘要 图像自编码通过“编码-解码-重构”学习紧凑表征。本文用 ACERS 框架讲清原理、训练流程与工程应用,并给出最小可运行的 PyTorch 示例。 预计阅读时长:14~18 分钟 标签:autoencoder、image、pytorch SEO 关键词:图像自编码, Autoencoder, 重构 元描述:讲解图像自编码的核心机制与工程场景,含最小示例。 目标读者 想理解自编码器原理的入门读者 需要构建图像表示学习的工程实践者 关注异常检测与去噪应用的开发者 背景 / 动机 标注数据昂贵,但图像数据充足。 自编码器通过“重构输入”学习特征表示,适合无监督或弱监督场景。 在去噪、压缩、异常检测等任务中,自编码器是一条高性价比路径。 核心概念 编码器(Encoder):把图像压缩成低维特征。 解码器(Decoder):从特征重建图像。 重构损失:衡量输入与输出差异(MSE/MAE)。 A — Algorithm(题目与算法) 用通俗语言说明主题内容 图像自编码器的流程很直观: 把图像压缩为低维向量。 用低维向量重建图像。 用重构误差训练模型。 基础示例(1) 去噪自编码:输入带噪图像,输出干净图像。 基础示例(2) 异常检测:正常样本重构误差小,异常样本误差大。 实践指南 / 步骤 选择编码器/解码器结构(CNN 或 MLP)。 设定瓶颈维度(压缩比)。 选择重构损失(MSE/MAE)。 训练后用重构误差评估应用效果。 可运行示例(最小 PyTorch 自编码器) import torch import torch.nn as nn torch.manual_seed(42) class AE(nn.Module): def __init__(self): super().__init__() self.encoder = nn.Sequential( nn.Conv2d(1, 8, 3, stride=2, padding=1), nn.ReLU(), nn.Conv2d(8, 16, 3, stride=2, padding=1), nn.ReLU(), ) self.decoder = nn.Sequential( nn.ConvTranspose2d(16, 8, 4, stride=2, padding=1), nn.ReLU(), nn.ConvTranspose2d(8, 1, 4, stride=2, padding=1), nn.Sigmoid(), ) def forward(self, x): z = self.encoder(x) return self.decoder(z) x = torch.randn(4, 1, 28, 28) model = AE() out = model(x) print(out.shape) 解释与原理 编码器学习“压缩表示”,解码器学习“重构映射”。 重构损失逼近输入分布,从而学习数据结构。 去噪版本在输入端加噪,输出仍对齐原图。 C — Concepts(核心思想) 方法类型 自编码器属于无监督表示学习与生成式重构模型范式。 ...
副标题 / 摘要 ViT 把图像切成 patch 序列,再交给 Transformer 编码器处理。本文用 ACERS 框架拆解 ViT 的核心结构与工程选择,并提供最小可运行的 PyTorch 示例。 预计阅读时长:16~20 分钟 标签:vit、transformer、vision SEO 关键词:ViT, Vision Transformer, Patch Embedding, 图像分类 元描述:系统描述 ViT 架构与工程实践,含最小 PyTorch 示例。 目标读者 想理解 ViT 架构的入门读者 需要做视觉模型选型的工程实践者 想从 CNN 迁移到 Transformer 的开发者 背景 / 动机 CNN 通过局部卷积捕获特征,但长程依赖与全局建模能力有限。 ViT 把图像当成序列,直接用自注意力做全局建模, 在大规模数据预训练下表现非常强。 核心概念 Patch Embedding:将图像切成 patch 并线性投影。 Position Embedding:补充位置信息。 [CLS] Token:聚合全局特征用于分类。 Transformer Encoder:多头自注意力 + FFN 堆叠。 A — Algorithm(题目与算法) 用通俗语言说明主题内容 ViT 的核心流程: 把图像切成固定大小 patch。 每个 patch 拉平成向量并投影成 token。 加上位置编码和 [CLS] token。 送入 Transformer Encoder 得到全局表征。 用 [CLS] token 输出做分类。 基础示例(1) 图像 224x224,patch 16x16 → 196 个 patch + 1 个 [CLS]。 基础示例(2) 只保留编码器,就能做图像分类与检索。 实践指南 / 步骤 选择 patch 大小(8/16/32)。 设置隐藏维度与层数(如 12 层,768 维)。 添加位置编码与 [CLS] token。 训练:优先用预训练权重再微调。 可运行示例(最小 ViT 前向) import torch import torch.nn as nn torch.manual_seed(42) class MiniViT(nn.Module): def __init__(self, img_size=32, patch=8, dim=64, depth=2, heads=4): super().__init__() self.patch = patch self.unfold = nn.Unfold(kernel_size=patch, stride=patch) num_patches = (img_size // patch) ** 2 self.proj = nn.Linear(3 * patch * patch, dim) self.cls = nn.Parameter(torch.zeros(1, 1, dim)) self.pos = nn.Parameter(torch.zeros(1, num_patches + 1, dim)) enc_layer = nn.TransformerEncoderLayer(d_model=dim, nhead=heads, batch_first=True) self.encoder = nn.TransformerEncoder(enc_layer, num_layers=depth) self.head = nn.Linear(dim, 10) def forward(self, x): patches = self.unfold(x).transpose(1, 2) # B, N, patch_dim tokens = self.proj(patches) cls = self.cls.expand(x.size(0), -1, -1) tokens = torch.cat([cls, tokens], dim=1) + self.pos z = self.encoder(tokens) return self.head(z[:, 0]) x = torch.randn(2, 3, 32, 32) model = MiniViT() print(model(x).shape) 解释与原理 patch embedding 把图像变成序列。 self-attention 能在全局范围建模依赖。 [CLS] token 作为全局聚合向量用于分类。 C — Concepts(核心思想) 方法类型 ViT 属于基于注意力的视觉表征模型,用 Transformer Encoder 替代卷积堆叠。 ...