车间里真正难啃的从来不是模型精度,而是那条以秒计节拍的产线。我做过几个制造业的视觉检测项目,最开始也天真地以为把开源模型调通、在测试集上刷到 99% 就完事了,结果第一次进现场就被打回原形:光照一变,误检率翻三倍;换一批来料,模型直接失灵;质检员站在屏幕前盯了十分钟就说"这东西不如我自己看"。后来才慢慢明白,深度学习在制造业的落点其实有两块——一块是把人眼从重复的判定里替出来,也就是质量检测;另一块是拿检测出来的缺陷数据反过来去调工艺参数,也就是生产优化。前者是感知问题,后者是决策问题,两者共用同一套数据底座,但坑完全不一样。这篇东西写给正在或准备把深度学习往产线里塞的同行,从成像、标注、选型、部署一直讲到怎么让缺陷数据回流到工艺端,尽量把那些文档里不会写的细节摊开来说。
1. 车间里的真问题:质检工位为什么总在拖节拍
1.1 传统视觉方案在实机上失效的三个现场
先说清楚为什么大家要往深度学习上走。传统机器视觉那一套——模板匹配、边缘提取、阈值分割、Blob 分析——在结构化、高对比、缺陷形态固定的场景里其实非常好用,速度快、可解释、不需要 GPU。问题是制造业里大量的缺陷根本不长那个样子。
第一个现场是表面划伤检测。某精密结构件车间,铝合金外壳经过阳极氧化后要查表面。划伤的形态极不固定:有的是细长发丝线,有的是成片的雾状擦痕,有的在强反光区几乎看不见。传统方案用固定阈值分割,光源角度稍微偏两度,反光区域就从"背景"变成"缺陷",误检率直接飙到三成以上。质检员一天要复核上千件,复核本身变成了新的瓶颈。
第二个现场是装配完整性检查。某电子组装线要判断连接器是否插到位、卡扣是否闭合、密封圈有无漏装。这类缺陷的特点是"缺了东西"而不是"多了瑕疵",模板匹配遇到装配公差带来的位置微移就崩了,工位稍微有点震动,定位框飘一个像素就误判。而且这类缺陷样本极少——产线良率 99.5%,你一个月也攒不出几十张真缺陷图。
第三个现场是内部缺陷。铸件的气孔、焊缝的内部未熔合、复合材料的脱粘,肉眼和普通工业相机都看不见。这类场景传统视觉基本无解,得上 X 射线或超声,而成像本身噪声大、对比度低,缺陷边界模糊,人看都费劲。
这三个现场的共同点是:缺陷的形态无法用几条规则穷举,成像条件不稳定,而人对"什么算缺陷"的判断又带着模糊的容差。这正是深度学习能补位的地方——它不靠人写规则,而是从样本里学特征分布,对形变、光照、位置变化天然更宽容。
1.2 深度学习补的其实是"容差"这一块
很多介绍材料的说法是"深度学习精度更高",这个说法其实不准确,在规整场景里传统算法一样能到 99.9%,而且更快更便宜。深度学习真正补的是三件事。
第一是对非结构化形态的容忍度。卷积网络学的是纹理和局部结构的统计特征,划伤的走向变了、粗细变了、位置变了,只要局部纹理的统计特性相似,模型依然能给出高分响应。这也是为什么在表面缺陷这类形态发散的任务上,深度学习的收益最明显。
第二是抗成像波动。通过在训练集里主动注入光照变化、轻微位移、噪声、模糊,模型能学到对这类扰动的鲁棒性。传统算法靠参数硬扛,一个阈值定死,光变了就得重新调;模型是靠数据见过的多样性撑着。
第三是把判定标准从"写死的规则"变成"可标定的分布"。这一点常被忽略,但对生产管理其实更重要。传统算法的判定逻辑只有写代码的人懂,出了问题很难追溯;深度学习模型的输出是一个分数,你可以拿这个分数去做阈值标定、做分级、做趋势统计,甚至可以和工艺参数做相关性分析。后面讲生产优化的时候,这个"分数"就是最关键的数据资产。
不过这里要泼一盆冷水:深度学习不是万能的。缺陷样本极少(几十张以内)、缺陷与正常样本在像素层面几乎无差异、或者要求 100% 可解释可追溯的场景(某些安全件),纯深度学习方案往往不如"传统算法 + 深度学习复判"的组合来得稳。我自己在几个项目里的经验是,优先用传统算法做粗筛和定位,把 ROI 裁出来再送模型做精细判定,这样既能压推理耗时,又能降低背景干扰,模型收敛也快得多。
2. 成像与标注:模型的天花板在镜头前就定死了
2.1 光源、镜头、工位布局的取舍逻辑
我在项目复盘时最常说的一句话是:算法救不了烂图。一个检测项目最终能做到什么水平,七成在成像方案定下来的那一刻就决定了。模型再深,也变不出图里没有的信息。
光源是第一优先级。常见的几种打光方式各有适用面:
| 打光方式 | 适用缺陷类型 | 典型问题 |
|---|---|---|
| 低角度暗场 | 划伤、凹坑、表面凸起 | 对平面度敏感,工件翘曲会导致亮度不均 |
| 同轴光 | 镜面/高反材质上的细微划痕 | 反光强烈时需要加偏振片 |
| 背光/透射 | 轮廓尺寸、孔洞、缺料 | 只能看透光特征,表面缺陷看不到 |
| 穹顶无影光 | 曲面、复杂三维结构 | 对比度偏低,细小缺陷容易被抹平 |
| 多角度频闪 | 多面同时检测 | 结构复杂,成本和调试周期高 |
选光源的核心判断是:你要检的缺陷,在哪种打光下与正常区域的灰度/色彩差异最大?这一步必须在现场拿实物试,不能靠想象。我见过一个项目,方案评审时大家对着示意图觉得同轴光最合适,实物打光后发现该材质在同轴下几乎全反,缺陷完全淹没在反光里,最后改成低角度暗场 + 分区打光才解决,前后耽误了三周。
镜头选型要算三个数:视野(FOV)、工作距离(WD)、最小可分辨缺陷尺寸。行业里常用的经验是,要稳定检出某个尺寸的缺陷,像素分辨率至少要做到缺陷尺寸的 1/5 到 1/10。比如最小要检 0.1mm 的划伤,那单像素对应的实际尺寸最好在 0.01~0.02mm。算一下:视野 100mm × 100mm,像素精度 0.02mm,那至少需要 5000 × 5000 的分辨率,这个量级已经超出常规面阵相机,实际中要么缩小视野分段拍,要么上线扫。
工位布局里最容易被忽视的是触发与同步。产线在动,相机得在工件到位的那一瞬间拍,触发早了晚了都是废片。编码器触发比光电传感器触发稳定,尤其是输送带速度有波动的时候。还有一点,曝光时间要和产线速度匹配,速度 500mm/s、曝光 200μs,运动模糊就是 0.1mm,刚好把你的最小缺陷尺寸糊掉。很多现场"模型效果不好"的根因其实是运动模糊,回头查图才发现,缺陷在图上就是一团虚影。
2.2 小样本与类别极不均衡下的标注策略
制造业数据集的典型形态是:正常样本堆成山,缺陷样本按张数。良率 99% 意味着你有一万张正常图配一百张缺陷图,比例 100:1 起步,某些缺陷类型可能只有个位数样本。
先说标注。工业缺陷标注最大的成本不在画框,而在共识。同一个划伤,A 质检员判为轻微、B 判为致命,你让标注员怎么标?我在项目启动阶段一定会做一件事:组织一次"标注对齐会",把历史上判定有争议的样本挑出来,让质检、工艺、质量三方一起过一遍,形成一份带图例的判定标准文档。这份文档的价值远超它的工作量,因为后面模型的所有阈值、分级、报警逻辑,都是围绕它展开的。没有这份东西,模型训出来一定会陷入无休止的"这个为什么判成 NG"的扯皮。
再说数据层面的处理,几个实操上有效的做法:
一是把正常样本用足。缺陷检测里,正常样本不是废料。用无监督/自监督的异常检测思路(自编码器重建、特征嵌入的最近邻距离、PatchCore 这类基于预训练特征的记忆库方法),只用正常样本训练,推理时算异常分数,在缺陷样本极少时往往比监督学习更稳。我在一个只有四十多张真缺陷图的项目里,监督模型过拟合严重,换成特征记忆库方案后,召回从 71% 提到 89%,代价是推理慢了一些、需要针对新缺陷类型重新调阈值。
二是合成缺陷要有节制。CutPaste、随机贴图、纹理融合这些方法能有效扩充缺陷样本,但必须控制合成缺陷的"真实度"。合成太假,模型学到的是合成痕迹而不是缺陷特征,实测表现会崩。我的经验是合成样本占比不超过总缺陷样本的 50%,而且每一批合成样本都要人工抽检 20 张确认视觉上说得过去。
三是重采样与损失函数的组合使用。单纯过采样会让模型在少数类上过拟合,单纯改损失又可能欠拟合。比较稳的组合是:轻度过采样(把稀有类复制到总占比 10%~20%)+ Focal Loss 或类别加权交叉熵。下面是一个可以直接用的加权 Focal Loss 实现:
import torch import torch.nn as nn import torch.nn.functional as F class WeightedFocalLoss(nn.Module): def __init__(self, alpha=None, gamma=2.0, reduction='mean'): super().__init__() # alpha: 每个类别的权重张量,按类别频率的倒数归一化得到 self.alpha = alpha self.gamma = gamma self.reduction = reduction def forward(self, logits, target): log_prob = F.log_softmax(logits, dim=1) prob = log_prob.exp() target_log_prob = log_prob.gather(1, target.unsqueeze(1)).squeeze(1) focal_term = (1.0 - prob.gather(1, target.unsqueeze(1)).squeeze(1)) ** self.gamma loss = -focal_term * target_log_prob if self.alpha is not None: loss = loss * self.alpha[target] return loss.mean() if self.reduction == 'mean' else loss.sum() # 类别频率:[正常 0.97, 轻微 0.02, 致命 0.01] # 权重取频率倒数的开方,避免过度放大稀有类导致训练不稳 freq = torch.tensor([0.97, 0.02, 0.01]) alpha = (1.0 / freq).sqrt() alpha = alpha / alpha.sum() * len(alpha)注意alpha我用了频率倒数的开方而不是直接倒数,这是踩过坑的:直接用倒数,稀有类权重会被放大几十倍,训练前期梯度爆炸、loss 震荡,模型反而学不动。开方之后温和很多,收敛稳定。
3. 算法选型:和节拍、算力、误检成本对齐才叫合适
3.1 缺陷形态决定网络结构的选择
选模型这件事,很多人的思路是"哪个 SOTA 用哪个",实际项目里我基本不看榜单,只看三件事:缺陷是分类问题、定位问题还是分割问题;产线允许的单帧推理时间是多少;误检和漏检哪个代价更高。
按任务形态分,大致这么对应:
- 整件判合格/不合格,缺陷位置不重要 → 图像分类。用 ResNet、EfficientNet 这类骨干,输入裁到 224 或 384,速度快,实现简单。
- 需要知道缺陷在哪、多大、几个→ 目标检测。YOLO 系列在这个场景用得最多,原因是速度快、工程生态成熟、小目标优化方案多。铸件气孔、装配缺件这类都适合。
- 需要精确的缺陷面积和边界(比如划伤长度分级、涂层脱落面积占比) → 语义分割。U-Net 系结构是常规选择,但分割标注成本高,通常只在必须量化的场景才上。
- 缺陷样本极少、形态完全无法预判→ 异常检测。基于预训练特征的方法(特征嵌入 + 距离度量)是当前性价比最高的路线,不需要缺陷样本,只需要正常样本。
有个细节值得说:小目标检测在工业场景里是常态而不是特例。一个 4000×3000 的图上,缺陷可能只占 20×20 像素。直接缩放到 640 送入网络,这个缺陷就剩 3 个像素,模型根本看不见。常见的处理是切图推理——把大图切成带重叠的图块(比如 640×640,重叠 128),逐块推理后再把结果映射回原图做 NMS 合并。代价是推理次数变多,得靠批处理和 GPU 并行把时间压回来。另一个思路是保持高分辨率输入 + 使用带高分辨率分支的结构,但显存占用会明显上升,需要权衡。
3.2 阈值与判定逻辑:模型输出之后还有一层工程
这点我觉得是工业落地和学术研究最大的分水岭。学术上模型输出概率,取 argmax 就完事了;产线上,模型输出只是一个"证据",最终判定还得过一层业务逻辑。
为什么?因为误检和漏检的代价不对称。漏检一个致命缺陷,可能导致整批召回、客户投诉;误检一个正常件,只是多花人工复核的时间。两者的成本可能差两个数量级。所以在阈值设定上,不能统一取 0.5,而要按缺陷等级分别定。
我的做法是先画一张分类的代价矩阵,把每种判定错误的成本量化(哪怕是粗略的数量级估计),然后在这个约束下搜阈值。下面是按代价最小化搜阈值的思路:
import numpy as np from sklearn.metrics import confusion_matrix def search_threshold(y_true, y_score, cost_fn=100.0, cost_fp=1.0): """按期望代价最小化搜索判定阈值 y_true: 0=正常, 1=缺陷 cost_fn: 漏检代价, cost_fp: 误检代价 """ best_t, best_cost = 0.5, float('inf') for t in np.arange(0.05, 0.96, 0.01): pred = (y_score >= t).astype(int) tn, fp, fn, tp = confusion_matrix(y_true, pred, labels=[0, 1]).ravel() cost = fn * cost_fn + fp * cost_fp if cost < best_cost: best_cost, best_t = cost, t return best_t, best_cost除了阈值,工程上还会加几层后处理:
面积过滤。检测框面积小于某个值直接丢弃,能干掉大量噪点误检。这个下限要根据最小真实缺陷尺寸来定,不能拍脑袋。
连续性过滤。单帧检出但前后帧都没检出,大概率是偶发噪声。产线是连续拍摄的,用时间维度做一致性检查非常有效,成本极低。
分级与分流。检出缺陷不等于判废。轻微划伤可以放行或返修,致命缺陷直接剔除。模型输出分类 + 置信度,业务层按等级走不同路径,这样能把误检的影响控制在"多一次复核"而不是"误杀好件"。
人工复核队列。置信度落在中间区间(比如 0.4~0.7)的样本,不要硬判,直接推给人工。这条机制在项目初期特别重要,它既保证了产线不被误检拖垮,又能持续收集难例反哺模型。
4. 落地部署:从训练环境到产线边缘盒子的这段路
4.1 推理加速与产线节拍的对账
实验室里一张图推理 200ms 你觉得挺快,放到节拍 1.5 秒的产线上,加上取图、预处理、后处理、通信,实际可能就顶不住了。所以部署前第一件事是把整条链路的时间账算清楚,而不是只测模型前向耗时。
一个典型的单帧耗时拆解:
| 环节 | 典型耗时 | 优化手段 |
|---|---|---|
| 图像采集与传输 | 10~50ms | 用相机SDK直采,避免落盘再读 |
| 预处理(缩放、归一化) | 5~20ms | 用 GPU 做预处理,或固化到推理引擎 |
| 模型前向 | 20~200ms | 量化、剪枝、算子融合、换更轻的骨干 |
| 后处理(NMS、过滤) | 5~30ms | 用编译型实现替换 Python 循环 |
| 结果通信与落库 | 5~20ms | 异步写库,别阻塞主流程 |
优化顺序上,我的经验是先砍预处理和后处理,再动模型。很多项目里后处理用 Python 写的 NMS 加循环过滤,一帧能吃掉几十毫秒,换成向量化实现或者放到 GPU 上,几乎零成本就省下来了。模型本身可以走 ONNX 导出 + 推理引擎加速 + FP16/INT8 量化,通常能拿到 2~4 倍加速,但量化要做精度回归验证,尤其是小目标检测,INT8 量化后小目标的召回掉得可能比较明显,这时候可以对检测头部分保留 FP16。
还有个容易被忽略的点是批处理。如果产线是多工位并行拍摄,或者允许攒几帧一起处理,把 batch size 提上去,GPU 利用率能从 20% 提到 70% 以上,单帧均摊耗时降得很明显。
4.2 漂移、换型与模型迭代的日常运维
模型上线不是终点,是另一段麻烦的开始。工业现场的数据分布是会漂的,而且漂的原因五花八门:
- 光源老化,亮度缓慢衰减,几个月后图像整体偏暗;
- 换料批次,来料表面粗糙度或颜色有差异;
- 换型,同一产线切换不同型号产品,缺陷形态分布完全不同;
- 设备维护后相机位置微移,成像视场变了;
- 环境温湿度变化影响某些材质的成像表现。
这些漂移在指标上看就是"误检率缓慢爬升",如果没人管,三个月后质检员就会把系统关掉。所以要建立一套监控机制。
我一般会埋这几个指标,按天统计并画趋势:
一是判定分布。每天的 OK/NG 比例、各等级的占比。如果 NG 率突然从 1% 跳到 5%,要么是工艺出问题了,要么是模型漂了,两者都需要立刻查。
二是置信度分布。模型输出的分数直方图。如果分布整体左移(大家分数都变低了),通常意味着输入分布变了,模型"不确定"了。这个信号比准确率更敏感,因为它不需要真值就能算。
三是难例回流。所有人工复核过的样本自动入库,按周抽样做一次离线评估,看模型在这些样本上的表现。这是最直接的模型退化检测手段。
四是特征漂移检测。拿模型中间层特征或者输入图像的统计量(均值、方差、梯度分布),和基线做距离度量。这个偏工程化,实现成本高一些,但对早期预警很有效。
换型的处理策略要提前定。常见做法是一个底座模型 + 多个型号的轻量适配层,或者干脆每个型号一个独立模型,用配置切换。前者维护成本低但精度可能打折,后者精度好但模型数量会膨胀。我倾向于按型号差异程度决定:差异小的走统一模型 + 型号 embedding,差异大的直接分模型,别硬凑。
5. 从检出到调参:把缺陷数据反喂给工艺的闭环
5.1 缺陷标签与工艺参数的关联建模
前面说的都是"发现问题",生产优化是"解决问题"。这一步的价值其实比检测本身更大,因为它直接作用在良率上,而不是只省几个质检人力。
前提是数据要能对上。检测系统记录的每条缺陷,必须带上时间戳、工位号、设备号、批次号,然后和工艺侧的参数(温度、压力、速度、张力、模具号、环境温湿度)做时间对齐。这一步听起来简单,实际做起来很磨人,因为工艺参数的采集频率、时钟、字段命名各设备都不一样,经常出现"检测记录 14:32:15,注塑机参数记录 14:32:00 和 14:33:00 两条,对不上"的情况。我的做法是统一到秒级时间窗做聚合(取窗口内的均值/最大值),并强制所有设备做时钟同步,这一条在项目启动时就要提,越晚做越痛苦。
数据对齐之后,可以做几层分析:
第一层是描述性关联。按缺陷类型分组,看各组对应的工艺参数分布有没有差异。比如某类气孔缺陷集中的时段,模温是不是普遍偏低 3~5 度?这个用简单的分组统计加箱线图就能看出来,不需要复杂模型,但往往能直接给出工艺员的调整方向。
第二层是重要性分析。用随机森林、梯度提升树这类模型做特征重要性排序,找出对缺陷率影响最大的几个参数。制造业里参数动辄几十上百个,工艺员不可能全盯,能定位到 Top 5 就已经很有价值了。这里要注意共线性问题,模温、料温、冷却时间这几个参数往往高度相关,重要性排序会互相稀释,最好先做相关性筛选或者用 SHAP 值看边际贡献。
第三层是时序建模。有些缺陷不是瞬时参数导致的,而是累积效应。比如模具磨损、滤网堵塞、料筒积料,这些在参数上看不出突变,但会在时间序列上形成缓慢的趋势。用滑动窗口统计 + 趋势检测(或者简单的控制图规则)就能捕捉。我也试过用 LSTM/TCN 对工序时序建模预测缺陷概率,效果有提升但幅度有限,而且可解释性差、工艺员不买账,后来在多数项目里退回到"特征工程 + 树模型"的方案,性价比更高。
5.2 参数寻优与良率预测的落地边界
再往前一步就是主动优化:给定目标,反推最优参数组合。这件事在理论上很诱人,实操上要非常克制。
参数寻优的常见做法是贝叶斯优化。它的好处是样本效率高,不需要穷举,几十次试验就能逼近较优区域:
# 伪代码示意:以注塑工艺为例的参数寻优框架 # 目标:在满足尺寸公差的前提下最小化缺陷率 from skopt import gp_minimize from skopt.space import Real def evaluate(params): mold_temp, hold_press, cool_time = params # 下发参数 -> 等待稳定 -> 采集N模 -> 统计缺陷率 defect_rate, size_dev = run_trial(mold_temp, hold_press, cool_time) # 硬约束:尺寸超差直接给大惩罚 if size_dev > TOLERANCE: return 10.0 + size_dev return defect_rate space = [ Real(60, 90, name='mold_temp'), Real(30, 80, name='hold_press'), Real(8, 20, name='cool_time'), ] result = gp_minimize(evaluate, space, n_calls=40, n_initial_points=10, random_state=42)但落地时有三条边界必须认清:
边界一:优化的搜索空间必须由工艺员划定。你不能让算法在物理上不合理的区间里乱试,那会出废品甚至损坏设备。上下限、参数间的耦合约束(比如保压时间不能超过冷却时间)都要提前写死。
边界二:试验成本要算进目标函数。一次试验意味着停线、调机、跑几十模、检测、再调回来。这个成本可能是几千到几万不等。所以试验次数必须严格控制,通常一个优化周期不超过 40~60 次,而且要和正常生产排程错开。
边界三:小样本下的优化结果只能当"方向建议",不能当"指令"。40 次试验对一个三维参数空间来说仍然稀疏,优化器给出的最优点很可能落在噪声上。我的做法是:优化结果不作为自动下发参数,而是作为工艺员的参考建议,由人确认后再执行,并且执行后做效果验证。这样既保留了算法的价值,又不会因为一次错误的自动调参造成批量事故。
良率预测这块相对好落地,因为它不改动任何东西,风险为零。用历史数据训练一个缺陷率预测模型,在换型或新订单投产前,输入计划参数,输出预测缺陷率和主要风险点。这个功能在项目验收时特别受管理层欢迎,因为它能直接支撑排产决策。但要注意,模型只能外推到训练数据覆盖过的参数范围内,一旦超出范围,预测值不可信,必须在界面上给出置信区间和"超出适用范围"的告警。
6. 上线节奏与踩坑清单:几个项目里最贵的教训
6.1 试运行期的三条硬指标
模型训完、系统搭好,别急着宣布上线。我现在的标准流程是走双轨试运行:系统判定和人工判定同时跑,但系统的结果不参与放行决策,只做记录比对。这个阶段通常两到四周,长度取决于产线节拍和缺陷出现频率。
试运行期我看三个指标,缺一不可:
| 指标 | 说明 | 验收参考 |
|---|---|---|
| 漏检率 | 人工判 NG 但系统判 OK 的比例 | 必须为 0 或极低,致命缺陷零容忍 |
| 过杀率 | 人工判 OK 但系统判 NG 的比例 | 直接决定质检员愿不愿意用 |
| 判定一致性 | 系统与人工判定完全一致的比例 | 分等级看,致命缺陷要求 > 99% |
漏检率是底线,过杀率才是决定系统能不能活下来的关键。我见过一个项目,模型召回做到 99.5%,但过杀率 8%,结果质检员每天要复核几百件,工作量反而增加了,三个月后系统就被弃用了。过杀率控制在 1%~2% 以内,质检员才真正感受到减负。
还有一个隐性指标是响应速度的体感。产线上的人对延迟极其敏感,判定结果晚 0.5 秒出来,节拍就被打乱。所以界面上一定要有实时的状态指示,检测中、通过、NG、待复核,让人一眼知道现在什么情况。
6.2 那些事后看很明显、当时却绕不过去的坑
坑一:拿实验室的验证集指标当承诺。我在第一个项目里犯过这个错,测试集 98% 的准确率,进现场实测只有 76%。原因是实验室用的是挑出来的干净样本,现场是连续生产的全量图,背景杂、有油污、有反光、有工件摆放偏差。后来我改了流程:验证集必须从连续生产的两小时原始数据里随机抽,不做任何筛选。这个数字才是可交付的数字。
坑二:低估了标注一致性的破坏力。一个项目里两个标注员对"轻微划伤"的判断不一致率高达 30%,模型学出来自然摇摆。后来做了一次标准对齐会,把判定标准细化到"长度超过 X 毫米且深度可感知"这种可操作的程度,模型的表现立刻上了一个台阶。这件事的教训是:在标注上省的时间,会在后面调试时加倍还回来。
坑三:光源方案定得太早,模型跟着受罪。有个项目光源是沿用旧产线的,模型怎么调都差一口气,最后硬着头皮改光源,改完之后同样的模型召回提了十几个点。所以我现在坚持:成像方案要在模型开发之前做实拍验证,至少看一百张不同工况下的实拍图,确认缺陷在图上清晰可辨,再往下走。
坑四:忽略了工控机和边缘设备的稳定性。模型跑得好好的,某天突然崩了,查半天发现是边缘设备的散热不行,夏天机柜内温度飙到 50 度,GPU 降频甚至掉卡。工业现场的设备必须考虑宽温、防尘、长期运行的稳定性,消费级显卡塞进机柜是行不通的。还有断电恢复后服务能不能自启动、相机掉线能不能自动重连,这些都得提前测。
坑五:忘了和现有系统对接。检测系统不是孤岛,判定结果要进产线控制系统做剔除、要进质量系统做追溯、要进报表系统做统计。这些对接的工作量经常被严重低估,接口协议、字段映射、异常处理、数据一致性,每一项都能拖上一两周。项目排期时这块至少要留 20% 的缓冲。
坑六:把"模型更新"想得太简单。上线后收集了难例,想更新模型,结果发现更新完老型号的表现反而变差了,这叫灾难性遗忘。后来我的做法是每次都做全量数据回归测试,新模型必须在"历史所有版本的验证集"上都达标才能上线,宁可慢一点。同时保留模型版本管理和灰度切换能力,新模型先跑一周只记录不决策,确认没问题再切。
最后分享一个我觉得很实用的小习惯:每个项目都维护一份"失败样本册",把误检、漏检的典型样本截图存下来,标注当时的工况、参数、原因分析。这份册子在项目后期调参时价值极高,因为人对具体图片的记忆远比对话术的记忆强,翻一眼就知道上次那个问题是怎么解决的。我手里的几个项目,这份册子攒到几百张之后,基本上新出现的问题八成能在里面找到类似案例。
还有一个从实践里得来的判断:制造业的深度学习项目,成功与否往往不取决于算法有多先进,而取决于数据链路有多干净、判定标准有多明确、和人配合得有多顺。把这三件事做扎实,用最朴素的模型也能跑出好结果;这三件事做不好,堆再多的技巧也只是在给一个摇摇欲坠的地基刷漆。