这两年做计算机视觉落地,特别是工业视觉相关的项目时,我几乎绕不开一个词:异常检测。不管是手机外壳上的划痕、布料上的断纱,还是电路板上的漏焊,本质都是同一件事——在绝大多数正常样本中,把分布外的那一小撮揪出来。做这类任务的团队逐年增多,但一个尴尬的事实是:换一条产品线,往往就得重新标数据、重新调阈值,甚至重新训练一个模型。最近读到一篇标题相当有趣的论文,题目叫《One Language-Free Foundation Model Is Enough for Universal Vision Anomaly Detection》。直译过来是“一个无语言的基础模型就足以做通用的视觉异常检测”。这句话同时踩中了三个关键点:基础模型、无语言、通用。它指向一个我非常渴望落地的东西:一套模型,换场景不用重训。这篇文章我想从选题动机、可能的技术实现、复现时的细节,以及实际落地边界几个角度,完整拆一遍。1. 内容整体设计与思路拆解1.1 异常检测的本质与长期痛点异常检测任务的核心,不是告诉你“这是什么”,而是判断“这正常吗”。大部分工业场景没有足够多的异常样本,异常往往还是动态变化的。比如在一个零件表面,可能出现的划痕有几十种,每一种在光照、角度、批次不同时表现都不一样。你很难在训练阶段把所有异常都枚举出来。因此主流做法是学习“正常是什么”,推理时看输入是否偏离正常分布。这有点像门卫认识楼里所有住户,他不需要知道小偷长什么样,只要发现一个不属于住户的人,就会警惕。这里的长期痛点有三个:标注成本高、异常不可穷尽、场景迁移难。标注成本高体现在:正常样本容易收集,但异常样本需要专门用损坏件或仿真器产生,动辄几千张标注;异常不可穷尽在于缺陷模式会随工艺变化,半年后新材质出现,旧模型立刻失效;场景迁移难则表现为同一个模型换了拍摄角度或产品型号,准确率大幅下滑。所以“通用视觉异常检测”才这么有吸引力。基础模型的出现确实改变了不少事情。预训练基础模型在超大规模数据上学习过图像结构,不需要在目标域从头训练,只要适配它的特征表示就能得到不错效果。但这里出现一个新分支:语言-视觉基础模型和纯视觉基础模型。异常检测到底需要不需要语言?这成了关键选择。1.2 语言不是万能钥匙:CLIP路线的四道坎CLIP类方法的基本思路是利用预训练模型的文本编码器和视觉编码器,把类别标签变成句子,比如“a photo of a good object”,然后根据图像与文本的相似度判断有没有异常。这种思路在分类任务上确实有效,因为CLIP已经对齐了图像和文本语义。但在异常检测里,CLIP路线至少碰四个坎:第一,异常类型不可枚举。CLIP需要人为定义异常标签,比如“划痕”“裂纹”“污渍”,但真正在现场遇到的异常,可能是几种缺陷的混合,也可能是从来没见过的异物。你写不完所有异常的名字,模型就只能对见过的标签敏感。第二,语言粒度太粗。很多缺陷在视觉上是极细小的纹理差异,比如“磨砂表面局部亮度过高”,这种描述用自然语言很难准确表达,反而会干扰视觉特征。第三,跨语言语义偏移。同一个异常概念在不同语言中映射到不同的特征空间,如果产品线在多个国家部署,prompt和底层视觉对齐的稳定性会受影响。第四,工程上多了一套文本编码器。推理时要把图像特征和文本特征做相似度计算,多一个组件意味着多一处延迟、多一处内存占用,也不方便裁剪成轻量级模型。这四个坎并不表示CLIP路线不能用,而是说明它更适合“已知类别”或“粗粒度”的任务。如果要做一个通用异常检测模型,它的上限已经被语言定义给锁死了。所以“Language-Free”这个定位很有针对性:去掉文本编码器,直接用纯视觉特征来定义正常分布,专攻异常检测自身的问题。1.3 “一个无语言基础模型”想解决的问题标题里有三个定语,我一个个拆。先说“One”,意思是统一权重的单个模型,目标是换数据集、换domain不用重新微调,即使要调也只是调整阈值或者少量特征适配。第二个“Language-Free”,指的是内部没有文本编码器,不需要为每个异常类别撰写文本提示。第三个“Universal”,是对通用性的承诺:涵盖不同场景的异常检测。从标题推断,作者大概率是选择了一个在纯视觉自监督任务上训练好的基础模型,比如自带稠密特征提取能力的Vision Transformer,然后用它提取正常样本的特征分布。这样既避开了语言监督引入的偏差,又能利用大规模预训练学到的纹理、形状和上下文先验。这是我看到标题后得到的第一直觉,也是我认为整个设计成立的核心前提。我补充一下为什么这能提高“通用性”。纯视觉自监督模型在预训练时只关心“图像结构能否重建”或“局部特征能否对应”,所以学到的特征是视觉底层属性,和任务无关。异常检测本质上也只关心“结构和统计分布是否一致”,二者任务高度重合。当你把正常样本聚合到一个基础模型的特征空间上,不同场景只是分布位置不同,但检测机制可以完全共用。这正是“一个模型做所有场景”的底层逻辑。2. 核心方案:无语言基础模型的架构与设计思路2.1 整体pipeline:特征抽取、分布建模、异常评分以我见过的同领域方案推断,其架构大致可以拆成四个环节。第一环节是特征抽取:把输入图像切割成patch序列,借助基础模型的Transformer编码器得到每一层的token表示。一般取某个中间层的输出,而不是最终全局特征,因为中间层保留了更多的局部细节和空间结构。第二环节是正常特征分布建模:把训练集中所有正常图像的局部特征收集起来,放进一个特征库,或者用多元高斯分布对每个位置/每个patch的特征做参数估计。第三环节是异常评分:推理时,对每一块patch的特征计算它与特征库最相近邻居的距离,或者计算它落在正常分布内的似然概率。距离越远、概率越低,这块区域就越可能是异常。第四环节是生成分割图:把patch级别的异常分数上采样回原图分辨率,做一个高斯平滑或条件随机场,得到像素级异常热力图。整个过程其实没有“训练”一说,如果不需要适配,整个流程就是对特征做统计建模和距离计算,这也是基础模型能快速落地的重要原因。我在做技术选型时特别看重这一点:工程上最怕那种看起来效果好、但代码要微调几十个epoch的模型。无语言基础模型把绝大多数计算交给了预训练阶段,下游几乎零成本,这种优雅程度在工业场景里非常加分。2.2 为什么选择纯视觉特征而非多模态融合很多人会问:既然CLIP学到的特征已经这么好,为什么不用它做特征提取,只是去掉文本编码器呢?答案在于CLIP的视觉分支是在语言监督下训练的,它的特征空间受到了文本对齐的约束,会忽略大量语言不需要的视觉细节。异常检测恰恰需要这些细节,比如反光、局部毛刺、边缘形变。你能用“chip”或“scratch”概括一些现象,但概括意味着损失。纯视觉自监督模型就不同。以自编码和对比类任务为例,预训练迫使模型记住纹理、边界、朝向、部件关系等信息,因为它要重建或区分这些结构。这样的特征对“偏离正常”非常敏感。用一个不恰当但准确的说法:CLIP学习的是“图片里有什么物件”,纯视觉模型学习的是“这个画面是怎么组成的”。异常检测更需要后者。从工程角度看,纯视觉模型也更省事。没有文本编码器,输入的文本描述不存在,因此更换产品线时,不需要跟着修改prompt。这一个决策看起来很微小,但对系统稳定性影响极大:一条产线上如果每换一个型号都要调整prompt,运维成本会立刻失控。无语言设计等于从根上砍掉了这个变量。2.3 正常特征库与像素级分割的关键设计特征库的形式直接决定精度和资源占用。最原始的做法是把所有正常patch的特征向量全部存下来,推理时逐patch做k近邻搜索。好处是足够逼近真实分布,坏处是训练图片稍多,特征库就膨胀到几十万甚至上百万行,检索延迟和显存都无法接受。更常见的做法是先用聚类将所有正常特征压成几千个聚类中心,然后用这些中心代替原始向量做距离计算。聚类中心数量是一个关键参数:太少了欠拟合,太多了又退化成原始库。如果采用多元高斯建模,还要处理一个分布假设问题。实际正常样本往往不是严格的高斯分布,尤其在光照变化场景下,特征可能呈多峰分布。这时候我会在每个patch位置上分别建模局部高斯,再和全局特征做混合判断。像素级分割上,有两个细节需要重点注意:一是patch大小决定了缺陷的极限分辨率,patch太大,小缺陷会被平均掉;patch太小,单块特征的语义又不够丰富。我一般先定一个默认patch size,再根据目标缺陷最小尺寸反向调整。二是图像归一化必须和预训练模型完全一致,很多人复现失败就是栽在这一步——直接用了自己数据集的分均值,而没有用基础模型预训练时的归一化参数。还有一个容易被忽略的设计是尺度融合。单层特征只代表某一抽象等级,综合中间层和深层特征往往能同时抓到边缘细节和全局结构。可以浅层特征负责小缺陷,深层特征负责上下文一致性,再把两者拼接或以加权方式融合成最终异常得分。这样既能压低误报率,又能保住小目标。这部分通常是论文里模块最多的区域,也是最值得花时间抠细节的地方。3. 从论文到工程:复现与调参的高频细节3.1 数据准备与评估指标的选择先把数据准备好。异常检测常用的评估基准有MVTec AD、VisA、BTAD等,这些都覆盖了工业零件、织物、食品等多种类型。如果用论文的思路,通常应该先在MVTec AD的类别上验证,再去自建数据上检查迁移性。数据准备时,训练集只放正常样本;测试集同时包含正常样本和异常样本,但不能在训练阶段看测试集。这个要求听起来简单,实践中经常有人把异常样本混进训练集,最后指标虚高,真实场景一测就露馅。评估指标不能只看图像级的AUROC,否则你会发现模型只判断“整张图有没有缺陷”也能拿高分,但无法给出定位效果。工业场景对像素级定位的要求非常高,所以至少需要同时报告像素级AUROC和PRO曲线。所谓PRO曲线,是对每个连通域加权评估的曲线,比像素级AUROC对小目标的惩罚更合理。另外,如果业务方关注误报警比例,还要额外报告F1以及设定阈值下的误检率。不要默认0.5是合理的阈值,正常样本和异常样本得分分布往往严重不均衡,必须根据验证集上的分数分布选阈值。我常用的做法是画正常测试样本的异常分数直方图,取95%分位数作为初始阈值,然后结合专家意见在召回率和误检之间做权衡。3.2 训练与推理中的关键参数和取舍如果你的场景允许进行少量微调,有几个参数值得优先调。第一是使用哪个backbone以及使用哪几层特征。基础模型内部每层语义不同,对异常检测贡献也不同。通常深层基于全局语义,中途层偏局部纹理。在做baseline时我会先固定中间层,效果稳定后再尝试浅层融合。第二是patch size和stride。这会直接影响检测分辨率:stride设得很小时,相邻patch重叠多,特征图分辨率高,但计算量成倍增加;设得过大,缺陷区域可能被稀释。我一般会看训练图像的尺寸,让patch大约占图像的2%到4%。第三是特征维度。如果直接用基础模型输出的embedding,可能会有上千维,检索和存储成本都高。通常先用PCA降维到256或128维,再送入特征库。降维不影响太多精度,却能显著提速。推理阶段同样有取舍。如果用k近邻,k取太大会被远处异常样本影响,取太小又容易受噪点干扰。我习惯用k=5或k=10,再配合一个重归一化:先把特征向量L2归一化,距离计算改为余弦距离,会比欧式距离在光照变化下更稳。若采用高斯分布建模,需要小心协方差矩阵的奇异问题,样本少时我会加上一个很小的正则项,或者直接用对角协方差。这些细节写不进论文,却是复现效果经常出现巨大差异的真正来源。3.3 上线部署时需要注意的坑离线实验跑得再好,上线时还是会有不少坑。第一个是内存和延迟。如果特征库里有几十万条向量,即使kNN检索也扛不住生产环境每秒几十次的调用,更别说还要做像素级上采样。常用解法是聚类压缩特征库,再挂一个近似最近邻索引(比如利用哈希或向量数据库的ANN),把最耗时的检索压到毫秒级。第二个是数据漂移。产线上的照明、相机老化、产品批次变化,都会让特征分布逐渐偏移,原来设定的正常/异常分界线会失效。我建议定期用少量最近几小时正常样本做分布漂移检测,一旦发现正常样本的得分均值出现连续上升,就触发阈值重校准。第三个是缺陷形态变化。虽然模型可以做到通用检测,但不同产品线的最佳patch size和特征尺度可能不同,上线前必须为每条产线留存一个“调参卡”,记录阈值、特征层和尺度融合系数。这些参数应该由质检工程师和算法工程师一起确认,不要靠算法工程师主观拍板。这里我还想说一个工程技巧:如果工厂现场环境允许,尽量把图像变成固定分辨率输入,而不是直接resize原图。原因很简单,异常检测对绝对尺度敏感,2倍resize会把小划痕磨没,也会改变patch相对缺陷的大小。在产线部署时,尽量用同一个镜头工作距离和焦距,把物理分辨率先固定下来,再谈算法精度。4. 适用场景与落地边界:它能做和不能做的4.1 工业质检:最典型的受益者工业质检是这种无语言基础模型最直接的受益场景。工厂里的常见需求是:正常品管够,不良品太少,而且不良形态千奇百怪。过去每换一条产线,就要重新收集十万级正常样本做训练,遇到非标件新产品更是无从下手。有了通用基础模型后,理论上同一套特征模型可以覆盖不同品类,新产线只需要少量正常图片来确定阈值,不用重新训练。我在自己的测试中发现,这种思路在产品表面纹理类场景表现尤其好,比如金属外壳、陶瓷、塑料件;反而在背景复杂或镜面反射严重的场景上要更谨慎,因为正常分布本身就不稳定。需要提醒大家的是,“通用”不代表“零调试”。即使一个模型能做到跨场景检测,不同场景下的阈值和敏感度还是不一样。落地时最好把它当作一个“能快速适配的强底座”,而不是“装上就能用的黑盒”。团队里仍然需要有人会读异常热力图、会调阈值,只是训练和迭代成本大大降低了。4.2 医学影像与泛安防的延伸价值除了工业,医学影像和泛安防也有类似痛点。医学影像里,正常解剖结构相对清楚,异常通常表现为肿块、出血或低信号区,类型同样不可穷尽。无语言基础模型的优势是,不用提前定义“肿瘤像什么”,只需从大量正常影像中学习分布,这对少见病尤其有价值。需要注意的是,医疗场景对误报的容忍度极低,AI只能作为辅助定位工具,最终判断权必须保留给医生。所以这里的落地重心更多是“给出可疑区域热力图”,而不是硬分类。泛安防场景稍微复杂一些,比如道路异物、管道泄漏、园区夜间闯入。这些场景的背景变化剧烈,正常分布很难用静态模型概括。纯视觉基础模型如果是按离线分布训练的,就容易把正常的光影变化当成异常。我倾向于在安防场景使用“在线参考+离线底座”的混合方案:在线持续收集正常画面来更新参考分布,离线底座提供高层语义特征。这样的架构比单独使用一个冻结基础模型要稳得多。4.3 当前方法的局限和可以改进的方向任何技术都有边界,这篇标题再惊艳也不可能万能。我判断最大的局限在于对“正常分布”的定义是统计意义上的,它要求正常样本足够多、足够连续。如果少数正常样本之间差异本来就很大(比如同一型号有两种外观等级),模型会把它们视为两种模式,第三种微变反而会被漏检或误报。解决思路是在正常特征导入前先做一次模式分解,把这个场景拆成多个子分布,再分别建库。第二个局限是小目标与推理速度的矛盾。patch size缩小能捕捉小缺陷,但计算量指数上升,很难在边缘设备实时跑。轻量化方向可以尝试:用token剪枝机制,只对可疑区域做精细计算,或者把特征提取和异常评分拆成两段流水线,先粗筛再精判。第三个局限是极端异常的定义模糊。比如一个产品边缘磨损了20%,是异常还是正常?这已经超出视觉能回答的范围,需要结合物理量或规则。所以我认为未来更好的方向不是“纯视觉一把梭”,而是“视觉基础模型+轻量规则/物理约束”,用基础模型做特征入口,用业务规则做最后裁决。这可能是“通用视觉异常检测”真正可落地的形态。5. 我的实操体会与几个“反直觉”经验5.1 别急着换大模型,先把特征尺度对齐我见过许多团队拿到新方法后第一件事就是换更大的backbone,试图刷出更高指标。但以我的实操经验,复现无语言异常检测模型时,最常见的翻车点根本不在于模型大小,而在于预处理和尺度的对齐。图像resize方式、归一化均值、patch的重叠比例,这些细节如果和预训练设置不一致,差别会非常明显。有一次我在某数据集上把归一化参数换成了目标域自己的统计值,结果AUROC掉了近十个点。后来换回预训练参数,分数立刻恢复正常。从那以后我养成了习惯:先跑一遍zero-shot基线,确认代码链路没有问题,再考虑替换backbone或调参。5.2 决定异常检测效果的不是模型,而是特征空间的团簇性一开始我迷信复杂异常评分模块,花了很多时间调kNN参数和距离度量,结果始终卡在某个指标上。后来我把正常样本的特征投影到二维可视化,发现真正的问题是这些正常特征本身不够紧凑,它们分散成好几团。图像看上去都是正常品,但拍摄角度和光照变化导致特征迁移,模型自然会把某些正常区域判成异常。这让我意识到,与其在评分公式里找问题,不如回去检查数据采集的环境一致性。只要正常特征团簇性足够好,哪怕用最简单的欧式距离也能拿到理想分数。团簇性的度量可以在运行时监控:每隔一段批量抽样正常特征,计算类内平均距离,盯住这个值有没有变大。5.3 给团队落地时的一点建议最后分享一点贴近管理的经验。引入通用基础模型做异常检测,最大的收益不是单个指标的数字,而是把团队从“每天标注新缺陷”的泥潭里解放出来。我的建议是第一个项目不要贪多,先选一个异常类型相对稳定的产品线做单类别验证,把它跑成熟。跑通后,再逐步扩展新产线。每次引入新产线时,只做特征库更新和阈值校对,不要把底层模型结构又改一遍。系统要设计成“底座不动、参考库滑动更新”的形态。这样算法团队的精力可以放在难例分析和规则融合上,而不是永远在补数据、重训练。对我个人而言,这种可维护、可演进的通用方案,比单点性能刷榜更值得长期投入。
这两年做计算机视觉落地,特别是工业视觉相关的项目时,我几乎绕不开一个词:异常检测。不管是手机外壳上的划痕、布料上的断纱,还是电路板上的漏焊,本质都是同一件事——在绝大多数正常样本中,把分布外的那一小撮揪出来。做这类任务的团队逐年增多,但一个尴尬的事实是:换一条产品线,往往就得重新标数据、重新调阈值,甚至重新训练一个模型。最近读到一篇标题相当有趣的论文,题目叫《One Language-Free Foundation Model Is Enough for Universal Vision Anomaly Detection》。直译过来是“一个无语言的基础模型就足以做通用的视觉异常检测”。这句话同时踩中了三个关键点:基础模型、无语言、通用。它指向一个我非常渴望落地的东西:一套模型,换场景不用重训。这篇文章我想从选题动机、可能的技术实现、复现时的细节,以及实际落地边界几个角度,完整拆一遍。1. 内容整体设计与思路拆解1.1 异常检测的本质与长期痛点异常检测任务的核心,不是告诉你“这是什么”,而是判断“这正常吗”。大部分工业场景没有足够多的异常样本,异常往往还是动态变化的。比如在一个零件表面,可能出现的划痕有几十种,每一种在光照、角度、批次不同时表现都不一样。你很难在训练阶段把所有异常都枚举出来。因此主流做法是学习“正常是什么”,推理时看输入是否偏离正常分布。这有点像门卫认识楼里所有住户,他不需要知道小偷长什么样,只要发现一个不属于住户的人,就会警惕。这里的长期痛点有三个:标注成本高、异常不可穷尽、场景迁移难。标注成本高体现在:正常样本容易收集,但异常样本需要专门用损坏件或仿真器产生,动辄几千张标注;异常不可穷尽在于缺陷模式会随工艺变化,半年后新材质出现,旧模型立刻失效;场景迁移难则表现为同一个模型换了拍摄角度或产品型号,准确率大幅下滑。所以“通用视觉异常检测”才这么有吸引力。基础模型的出现确实改变了不少事情。预训练基础模型在超大规模数据上学习过图像结构,不需要在目标域从头训练,只要适配它的特征表示就能得到不错效果。但这里出现一个新分支:语言-视觉基础模型和纯视觉基础模型。异常检测到底需要不需要语言?这成了关键选择。1.2 语言不是万能钥匙:CLIP路线的四道坎CLIP类方法的基本思路是利用预训练模型的文本编码器和视觉编码器,把类别标签变成句子,比如“a photo of a good object”,然后根据图像与文本的相似度判断有没有异常。这种思路在分类任务上确实有效,因为CLIP已经对齐了图像和文本语义。但在异常检测里,CLIP路线至少碰四个坎:第一,异常类型不可枚举。CLIP需要人为定义异常标签,比如“划痕”“裂纹”“污渍”,但真正在现场遇到的异常,可能是几种缺陷的混合,也可能是从来没见过的异物。你写不完所有异常的名字,模型就只能对见过的标签敏感。第二,语言粒度太粗。很多缺陷在视觉上是极细小的纹理差异,比如“磨砂表面局部亮度过高”,这种描述用自然语言很难准确表达,反而会干扰视觉特征。第三,跨语言语义偏移。同一个异常概念在不同语言中映射到不同的特征空间,如果产品线在多个国家部署,prompt和底层视觉对齐的稳定性会受影响。第四,工程上多了一套文本编码器。推理时要把图像特征和文本特征做相似度计算,多一个组件意味着多一处延迟、多一处内存占用,也不方便裁剪成轻量级模型。这四个坎并不表示CLIP路线不能用,而是说明它更适合“已知类别”或“粗粒度”的任务。如果要做一个通用异常检测模型,它的上限已经被语言定义给锁死了。所以“Language-Free”这个定位很有针对性:去掉文本编码器,直接用纯视觉特征来定义正常分布,专攻异常检测自身的问题。1.3 “一个无语言基础模型”想解决的问题标题里有三个定语,我一个个拆。先说“One”,意思是统一权重的单个模型,目标是换数据集、换domain不用重新微调,即使要调也只是调整阈值或者少量特征适配。第二个“Language-Free”,指的是内部没有文本编码器,不需要为每个异常类别撰写文本提示。第三个“Universal”,是对通用性的承诺:涵盖不同场景的异常检测。从标题推断,作者大概率是选择了一个在纯视觉自监督任务上训练好的基础模型,比如自带稠密特征提取能力的Vision Transformer,然后用它提取正常样本的特征分布。这样既避开了语言监督引入的偏差,又能利用大规模预训练学到的纹理、形状和上下文先验。这是我看到标题后得到的第一直觉,也是我认为整个设计成立的核心前提。我补充一下为什么这能提高“通用性”。纯视觉自监督模型在预训练时只关心“图像结构能否重建”或“局部特征能否对应”,所以学到的特征是视觉底层属性,和任务无关。异常检测本质上也只关心“结构和统计分布是否一致”,二者任务高度重合。当你把正常样本聚合到一个基础模型的特征空间上,不同场景只是分布位置不同,但检测机制可以完全共用。这正是“一个模型做所有场景”的底层逻辑。2. 核心方案:无语言基础模型的架构与设计思路2.1 整体pipeline:特征抽取、分布建模、异常评分以我见过的同领域方案推断,其架构大致可以拆成四个环节。第一环节是特征抽取:把输入图像切割成patch序列,借助基础模型的Transformer编码器得到每一层的token表示。一般取某个中间层的输出,而不是最终全局特征,因为中间层保留了更多的局部细节和空间结构。第二环节是正常特征分布建模:把训练集中所有正常图像的局部特征收集起来,放进一个特征库,或者用多元高斯分布对每个位置/每个patch的特征做参数估计。第三环节是异常评分:推理时,对每一块patch的特征计算它与特征库最相近邻居的距离,或者计算它落在正常分布内的似然概率。距离越远、概率越低,这块区域就越可能是异常。第四环节是生成分割图:把patch级别的异常分数上采样回原图分辨率,做一个高斯平滑或条件随机场,得到像素级异常热力图。整个过程其实没有“训练”一说,如果不需要适配,整个流程就是对特征做统计建模和距离计算,这也是基础模型能快速落地的重要原因。我在做技术选型时特别看重这一点:工程上最怕那种看起来效果好、但代码要微调几十个epoch的模型。无语言基础模型把绝大多数计算交给了预训练阶段,下游几乎零成本,这种优雅程度在工业场景里非常加分。2.2 为什么选择纯视觉特征而非多模态融合很多人会问:既然CLIP学到的特征已经这么好,为什么不用它做特征提取,只是去掉文本编码器呢?答案在于CLIP的视觉分支是在语言监督下训练的,它的特征空间受到了文本对齐的约束,会忽略大量语言不需要的视觉细节。异常检测恰恰需要这些细节,比如反光、局部毛刺、边缘形变。你能用“chip”或“scratch”概括一些现象,但概括意味着损失。纯视觉自监督模型就不同。以自编码和对比类任务为例,预训练迫使模型记住纹理、边界、朝向、部件关系等信息,因为它要重建或区分这些结构。这样的特征对“偏离正常”非常敏感。用一个不恰当但准确的说法:CLIP学习的是“图片里有什么物件”,纯视觉模型学习的是“这个画面是怎么组成的”。异常检测更需要后者。从工程角度看,纯视觉模型也更省事。没有文本编码器,输入的文本描述不存在,因此更换产品线时,不需要跟着修改prompt。这一个决策看起来很微小,但对系统稳定性影响极大:一条产线上如果每换一个型号都要调整prompt,运维成本会立刻失控。无语言设计等于从根上砍掉了这个变量。2.3 正常特征库与像素级分割的关键设计特征库的形式直接决定精度和资源占用。最原始的做法是把所有正常patch的特征向量全部存下来,推理时逐patch做k近邻搜索。好处是足够逼近真实分布,坏处是训练图片稍多,特征库就膨胀到几十万甚至上百万行,检索延迟和显存都无法接受。更常见的做法是先用聚类将所有正常特征压成几千个聚类中心,然后用这些中心代替原始向量做距离计算。聚类中心数量是一个关键参数:太少了欠拟合,太多了又退化成原始库。如果采用多元高斯建模,还要处理一个分布假设问题。实际正常样本往往不是严格的高斯分布,尤其在光照变化场景下,特征可能呈多峰分布。这时候我会在每个patch位置上分别建模局部高斯,再和全局特征做混合判断。像素级分割上,有两个细节需要重点注意:一是patch大小决定了缺陷的极限分辨率,patch太大,小缺陷会被平均掉;patch太小,单块特征的语义又不够丰富。我一般先定一个默认patch size,再根据目标缺陷最小尺寸反向调整。二是图像归一化必须和预训练模型完全一致,很多人复现失败就是栽在这一步——直接用了自己数据集的分均值,而没有用基础模型预训练时的归一化参数。还有一个容易被忽略的设计是尺度融合。单层特征只代表某一抽象等级,综合中间层和深层特征往往能同时抓到边缘细节和全局结构。可以浅层特征负责小缺陷,深层特征负责上下文一致性,再把两者拼接或以加权方式融合成最终异常得分。这样既能压低误报率,又能保住小目标。这部分通常是论文里模块最多的区域,也是最值得花时间抠细节的地方。3. 从论文到工程:复现与调参的高频细节3.1 数据准备与评估指标的选择先把数据准备好。异常检测常用的评估基准有MVTec AD、VisA、BTAD等,这些都覆盖了工业零件、织物、食品等多种类型。如果用论文的思路,通常应该先在MVTec AD的类别上验证,再去自建数据上检查迁移性。数据准备时,训练集只放正常样本;测试集同时包含正常样本和异常样本,但不能在训练阶段看测试集。这个要求听起来简单,实践中经常有人把异常样本混进训练集,最后指标虚高,真实场景一测就露馅。评估指标不能只看图像级的AUROC,否则你会发现模型只判断“整张图有没有缺陷”也能拿高分,但无法给出定位效果。工业场景对像素级定位的要求非常高,所以至少需要同时报告像素级AUROC和PRO曲线。所谓PRO曲线,是对每个连通域加权评估的曲线,比像素级AUROC对小目标的惩罚更合理。另外,如果业务方关注误报警比例,还要额外报告F1以及设定阈值下的误检率。不要默认0.5是合理的阈值,正常样本和异常样本得分分布往往严重不均衡,必须根据验证集上的分数分布选阈值。我常用的做法是画正常测试样本的异常分数直方图,取95%分位数作为初始阈值,然后结合专家意见在召回率和误检之间做权衡。3.2 训练与推理中的关键参数和取舍如果你的场景允许进行少量微调,有几个参数值得优先调。第一是使用哪个backbone以及使用哪几层特征。基础模型内部每层语义不同,对异常检测贡献也不同。通常深层基于全局语义,中途层偏局部纹理。在做baseline时我会先固定中间层,效果稳定后再尝试浅层融合。第二是patch size和stride。这会直接影响检测分辨率:stride设得很小时,相邻patch重叠多,特征图分辨率高,但计算量成倍增加;设得过大,缺陷区域可能被稀释。我一般会看训练图像的尺寸,让patch大约占图像的2%到4%。第三是特征维度。如果直接用基础模型输出的embedding,可能会有上千维,检索和存储成本都高。通常先用PCA降维到256或128维,再送入特征库。降维不影响太多精度,却能显著提速。推理阶段同样有取舍。如果用k近邻,k取太大会被远处异常样本影响,取太小又容易受噪点干扰。我习惯用k=5或k=10,再配合一个重归一化:先把特征向量L2归一化,距离计算改为余弦距离,会比欧式距离在光照变化下更稳。若采用高斯分布建模,需要小心协方差矩阵的奇异问题,样本少时我会加上一个很小的正则项,或者直接用对角协方差。这些细节写不进论文,却是复现效果经常出现巨大差异的真正来源。3.3 上线部署时需要注意的坑离线实验跑得再好,上线时还是会有不少坑。第一个是内存和延迟。如果特征库里有几十万条向量,即使kNN检索也扛不住生产环境每秒几十次的调用,更别说还要做像素级上采样。常用解法是聚类压缩特征库,再挂一个近似最近邻索引(比如利用哈希或向量数据库的ANN),把最耗时的检索压到毫秒级。第二个是数据漂移。产线上的照明、相机老化、产品批次变化,都会让特征分布逐渐偏移,原来设定的正常/异常分界线会失效。我建议定期用少量最近几小时正常样本做分布漂移检测,一旦发现正常样本的得分均值出现连续上升,就触发阈值重校准。第三个是缺陷形态变化。虽然模型可以做到通用检测,但不同产品线的最佳patch size和特征尺度可能不同,上线前必须为每条产线留存一个“调参卡”,记录阈值、特征层和尺度融合系数。这些参数应该由质检工程师和算法工程师一起确认,不要靠算法工程师主观拍板。这里我还想说一个工程技巧:如果工厂现场环境允许,尽量把图像变成固定分辨率输入,而不是直接resize原图。原因很简单,异常检测对绝对尺度敏感,2倍resize会把小划痕磨没,也会改变patch相对缺陷的大小。在产线部署时,尽量用同一个镜头工作距离和焦距,把物理分辨率先固定下来,再谈算法精度。4. 适用场景与落地边界:它能做和不能做的4.1 工业质检:最典型的受益者工业质检是这种无语言基础模型最直接的受益场景。工厂里的常见需求是:正常品管够,不良品太少,而且不良形态千奇百怪。过去每换一条产线,就要重新收集十万级正常样本做训练,遇到非标件新产品更是无从下手。有了通用基础模型后,理论上同一套特征模型可以覆盖不同品类,新产线只需要少量正常图片来确定阈值,不用重新训练。我在自己的测试中发现,这种思路在产品表面纹理类场景表现尤其好,比如金属外壳、陶瓷、塑料件;反而在背景复杂或镜面反射严重的场景上要更谨慎,因为正常分布本身就不稳定。需要提醒大家的是,“通用”不代表“零调试”。即使一个模型能做到跨场景检测,不同场景下的阈值和敏感度还是不一样。落地时最好把它当作一个“能快速适配的强底座”,而不是“装上就能用的黑盒”。团队里仍然需要有人会读异常热力图、会调阈值,只是训练和迭代成本大大降低了。4.2 医学影像与泛安防的延伸价值除了工业,医学影像和泛安防也有类似痛点。医学影像里,正常解剖结构相对清楚,异常通常表现为肿块、出血或低信号区,类型同样不可穷尽。无语言基础模型的优势是,不用提前定义“肿瘤像什么”,只需从大量正常影像中学习分布,这对少见病尤其有价值。需要注意的是,医疗场景对误报的容忍度极低,AI只能作为辅助定位工具,最终判断权必须保留给医生。所以这里的落地重心更多是“给出可疑区域热力图”,而不是硬分类。泛安防场景稍微复杂一些,比如道路异物、管道泄漏、园区夜间闯入。这些场景的背景变化剧烈,正常分布很难用静态模型概括。纯视觉基础模型如果是按离线分布训练的,就容易把正常的光影变化当成异常。我倾向于在安防场景使用“在线参考+离线底座”的混合方案:在线持续收集正常画面来更新参考分布,离线底座提供高层语义特征。这样的架构比单独使用一个冻结基础模型要稳得多。4.3 当前方法的局限和可以改进的方向任何技术都有边界,这篇标题再惊艳也不可能万能。我判断最大的局限在于对“正常分布”的定义是统计意义上的,它要求正常样本足够多、足够连续。如果少数正常样本之间差异本来就很大(比如同一型号有两种外观等级),模型会把它们视为两种模式,第三种微变反而会被漏检或误报。解决思路是在正常特征导入前先做一次模式分解,把这个场景拆成多个子分布,再分别建库。第二个局限是小目标与推理速度的矛盾。patch size缩小能捕捉小缺陷,但计算量指数上升,很难在边缘设备实时跑。轻量化方向可以尝试:用token剪枝机制,只对可疑区域做精细计算,或者把特征提取和异常评分拆成两段流水线,先粗筛再精判。第三个局限是极端异常的定义模糊。比如一个产品边缘磨损了20%,是异常还是正常?这已经超出视觉能回答的范围,需要结合物理量或规则。所以我认为未来更好的方向不是“纯视觉一把梭”,而是“视觉基础模型+轻量规则/物理约束”,用基础模型做特征入口,用业务规则做最后裁决。这可能是“通用视觉异常检测”真正可落地的形态。5. 我的实操体会与几个“反直觉”经验5.1 别急着换大模型,先把特征尺度对齐我见过许多团队拿到新方法后第一件事就是换更大的backbone,试图刷出更高指标。但以我的实操经验,复现无语言异常检测模型时,最常见的翻车点根本不在于模型大小,而在于预处理和尺度的对齐。图像resize方式、归一化均值、patch的重叠比例,这些细节如果和预训练设置不一致,差别会非常明显。有一次我在某数据集上把归一化参数换成了目标域自己的统计值,结果AUROC掉了近十个点。后来换回预训练参数,分数立刻恢复正常。从那以后我养成了习惯:先跑一遍zero-shot基线,确认代码链路没有问题,再考虑替换backbone或调参。5.2 决定异常检测效果的不是模型,而是特征空间的团簇性一开始我迷信复杂异常评分模块,花了很多时间调kNN参数和距离度量,结果始终卡在某个指标上。后来我把正常样本的特征投影到二维可视化,发现真正的问题是这些正常特征本身不够紧凑,它们分散成好几团。图像看上去都是正常品,但拍摄角度和光照变化导致特征迁移,模型自然会把某些正常区域判成异常。这让我意识到,与其在评分公式里找问题,不如回去检查数据采集的环境一致性。只要正常特征团簇性足够好,哪怕用最简单的欧式距离也能拿到理想分数。团簇性的度量可以在运行时监控:每隔一段批量抽样正常特征,计算类内平均距离,盯住这个值有没有变大。5.3 给团队落地时的一点建议最后分享一点贴近管理的经验。引入通用基础模型做异常检测,最大的收益不是单个指标的数字,而是把团队从“每天标注新缺陷”的泥潭里解放出来。我的建议是第一个项目不要贪多,先选一个异常类型相对稳定的产品线做单类别验证,把它跑成熟。跑通后,再逐步扩展新产线。每次引入新产线时,只做特征库更新和阈值校对,不要把底层模型结构又改一遍。系统要设计成“底座不动、参考库滑动更新”的形态。这样算法团队的精力可以放在难例分析和规则融合上,而不是永远在补数据、重训练。对我个人而言,这种可维护、可演进的通用方案,比单点性能刷榜更值得长期投入。