资讯动态

基于深度学习的钢铁缺陷识别与产线部署实践

发布时间:2026/10/27 11:26:33 来源:尧图企业网站定制
三年前我第一次被拉到某钢厂冷轧精整线的尾端站在那条跑得飞快的带钢旁边手里攥着一份“人工开卷检查”的排班表。检查工拿着手电筒趴在带钢上找缺陷一卷几千米眼睛盯到发花漏检全靠运气一卷判级判错就是几万块的损失。那一刻我脑子里只有一个念头这事儿必须交给深度学习来做靠人眼和传统算子已经顶不住了。基于深度学习的钢铁缺陷识别说白了就是用卷积网络代替人眼在带钢、板坯、棒材甚至铸坯表面上自动找出裂纹、夹杂、划痕、麻点这些毛病并且把位置、类别、尺寸一起报出来。它解决的核心问题不是“能不能看见”而是“在每秒几米的生产节拍下、在油污粉尘和反光干扰下稳定地把缺陷和正常纹理分开同时把过杀率压到产线能接受的水平”。这套东西适合谁来参考如果你是在工厂里做自动化改造的工程师看第三、五章就够上手如果你是做视觉算法的第二、四章的数据和调参细节更对胃口如果你只是刚接触工业质检的学生或者转行者前面两章的背景和路线对比能帮你少走半年弯路。我下面写的是我自己从数据集搭建、模型训练到产线部署踩过来的完整链路包含大量“文档里不会写、但现场一定会遇到”的细节。很多环节的结论和网上教程是反着来的比如数据增强不能随便翻转、评估指标不能只看准确率、模型精度往往不是瓶颈而存储带宽才是。1. 先想清楚钢铁缺陷检测为什么必须换赛道1.1 传统机器视觉方案的天花板到底在哪很多工厂在换深度学习之前其实已经上过一套基于传统算子的视觉系统打一束条形光用高分辨率相机拍灰度图然后做中值滤波、Sobel 边缘、阈值分割、形态学闭运算最后按面积和长宽比判缺陷。这套方案在缺陷对比度高、背景干净的场景下确实能跑比如某些镀层表面的明显划伤。但只要换个钢种、换一批来料、换一个班次的照明状态阈值就得重调调完这一批好使下一批又崩。根本原因在于钢铁表面缺陷的“特征”根本不是几何特征。裂纹可能只有几个像素宽、灰度差不到 10 个灰阶和轧制纹路、氧化皮残留、水渍在低层特征上几乎无法区分。传统算子做的是“人工定义规则”而人的规则表达能力有上限深度学习做的是“从数据里学规则”它能利用纹理的上下文、缺陷的走向连续性、周边区域的统计分布这些很难用公式写出来的东西。我做过一个对比同一批含夹杂和氧化皮压入的样本传统方案在调到最优阈值时召回率 76%、过杀率 18%换成一个只有 4.7M 参数的轻量分类网络召回率 93%、过杀率 6%。这个差距不是调参能补上的是方法论层面的代差。但我也要说句公道话传统算子不是没用。在整套系统里它最适合干“粗定位”和“异常初筛”的活——用简单的行列灰度投影、局部方差突变先把可疑区域圈出来把送给神经网络的图像面积压缩到原来的 1%5%。这一步省下来的算力比你在模型上抠十天参数都值钱。1.2 工业现场的四道硬约束决定了你所有的技术选型做学术数据集调模型你只需要关心 mAP做产线系统你要同时被四根绳子拴着任何一根断了系统就废了。第一根是节拍。精整线带钢速度常见 25 m/s高端线更快。假设检测精度要求 0.1 mm/pixel线速度 3 m/s那么线阵相机的行频必须是 3000 / 0.1 30000 行/秒也就是 30 kHz。这个行频下单台 8K 灰度相机每秒吐出约 8192 × 30000 × 1 字节 ≈ 245 MB 的原始数据双相机拼一幅 16000 像素宽的全幅图数据量直接翻倍。你没有可能把这玩意儿全存下来更没可能全送进 GPU。所以架构上必须做“选择性留存 分级筛查”这一点后面第五章会展开算。第二根是精度。客户不会跟你说“mAP 要到多少”他们说的是“漏检率低于 0.5%过杀率不高于 5%”。注意这两个指标是互相拉扯的你把置信度阈值调低漏检下去了过杀立刻上来产线因为频繁误报停机班组长第二天就来找你。真正可用的工作点是在过杀率约束下把召回做到最高而不是追求某个单一指标的漂亮数字。第三根是光照与污染。钢厂环境里镜头一天不擦就一层灰轧机乳化液飞溅、氧化铁皮粉尘、水雾全都会落在镜头和光源罩上。这意味着你的模型必须对“整体对比度缓慢下降”这件事有鲁棒性而不是只在你实验室那套打光下有效。第四根是样本。缺陷是小概率事件一条线一天可能就出几十个缺陷你要凑够每类几千张标注样本往往要攒几个月甚至跨产线收集。所以少样本、类别不均衡、标注成本这三件事从一开始就得设计进方案里不能等训练崩了再补。2. 数据集这件事决定了项目八成的成败2.1 公开数据集只能用来验证思路别指望它上线业内流传比较广的公开钢材表面缺陷数据集一般是六类典型缺陷、几百到一千多张图、200×200 左右的灰度图类别包括夹杂物、斑块、麻点、氧化皮压入、划痕、裂纹。拿来跑通流程、对比几个骨干网络、验证损失函数有没有写错它非常好用。但我必须直说拿它训出来的模型直接上线一次都不会成功。原因有三个。第一是成像条件完全不同公开集是离线采集、打光均匀、背景干净的裁剪块产线是线扫、有反光带、有周期性轧制纹路。第二是缺陷尺度分布不同公开集里缺陷基本占满画面产线上一个 0.3 mm 的点状麻点在 512×512 的图里可能只占 3×3 个像素。第三是类别定义不同公开集的“斑块”和产线上的“氧化皮压入”在视觉上高度相似你按公开集的标签体系训练上线后必然出现大量类别混淆。我的做法是公开集只用来做两件事——快速验证训练脚本和损失函数是否正常loss 能不能收敛、能不能过拟合一个小批次以及做骨干网络的初步选型对比。真正的训练集必须从目标产线自己采。2.2 类别定义与标注规范这是最容易翻车的地方你现在让三个老师傅去标同一批图他们给出的标签一致率可能只有 70%。这不是他们不专业是缺陷本身的边界就模糊。所以正式标注之前必须先把标签体系定死写成一张表标注人员照着执行。缺陷类别视觉特征标注边界规则常见混淆对象裂纹细长、走向连续、灰度偏暗、两端渐细按可见连续性框完整条断开超过 5 mm 拆成两个划痕、轧制纹夹杂块状或条带状、内部灰度不均、边界清晰沿外轮廓紧贴框选不含周边过渡区氧化皮压入、斑块划痕直线或弧线、宽度均匀、常成组平行只框划痕本体不含机械压痕裂纹、导板擦伤麻点密集点状、直径常在 1 mm 以下密集区整体框一个稀疏点逐个框氧化铁皮颗粒、水渍氧化皮压入不规则片状、边缘参差、灰度深浅混杂整片框选允许包含内部正常区夹杂、斑块辊印周期性横向条纹、间距与辊径对应整条周期性区域框选标注周期振动纹、来料原始条纹规范之外还有两个动作必须做。一是双人交叉复核任何一张图至少两个人标过不一致的进仲裁队列由工艺工程师拍板。二是负样本要主动收集很多人只标缺陷结果模型没见过“长得像缺陷的正常纹理”一上线到处误报。我通常会按 1:3 到 1:5 的比例加入难负样本专门挑那些曾经误报过的区域重新标注为“正常”这部分数据的价值比额外的正样本高得多。提示标注工具里一定要保留“不确定”这个选项。强迫标注员在二选一里猜最后污染的是整个数据集而且你事后根本查不出来哪些是猜的。2.3 数据增强有边界钢厂的图和自然图像不是一回事网上讲数据增强的文章一上来就是随机旋转、随机裁剪、色彩抖动、MixUp。放到钢铁缺陷上其中一半是毒药。随机旋转要禁用或者严格限制。轧制方向是有物理意义的裂纹基本沿轧向延伸辊印是横向周期性条纹你把图转 90 度裂纹变成横向模型学到的方向先验就被破坏了。我一般只允许 ±5 度以内的小角度旋转或者直接不转。水平/垂直翻转要分情况。对于斑块、麻点这类各向同性的缺陷翻转没问题对于裂纹、划痕这种有明确走向的翻转相当于凭空造了一批现实中不存在的样本会拉低模型对走向的敏感度。稳妥做法是只在各向同性类别上开翻转。真正有效的是这几类亮度和对比度的随机扰动模拟光源老化和镜头污染、高斯噪声和模糊模拟对焦漂移、随机遮挡小块模拟水滴和粉尘遮挡、以及针对小样本缺陷的 Copy-Paste——把标注好的缺陷实例抠出来随机贴到正常背景上。Copy-Paste 对小样本类别特别管用我用它把夹杂类的样本量从 300 张扩到 4000 张那一类的召回直接从 68% 拉到 88%。但注意贴合边缘要做羽化和泊松融合硬贴会产生明显的接缝伪影模型会去学那个接缝而不是缺陷本身。import random, cv2, numpy as np def industrial_augment(img, label, defect_cls): # 各向同性类别才允许翻转 isotropic {pitted, patch, inclusion} if defect_cls in isotropic: if random.random() 0.5: img cv2.flip(img, 1) # 小角度旋转绝不 90 度 if random.random() 0.3: ang random.uniform(-5, 5) h, w img.shape[:2] M cv2.getRotationMatrix2D((w / 2, h / 2), ang, 1.0) img cv2.warpAffine(img, M, (w, h), borderModecv2.BORDER_REFLECT) # 光照扰动模拟镜头污染导致的对比度衰减 if random.random() 0.5: alpha random.uniform(0.75, 1.15) # 对比度 beta random.uniform(-18, 18) # 亮度偏移 img np.clip(img.astype(np.float32) * alpha beta, 0, 255).astype(np.uint8) # 高斯模糊模拟对焦漂移与粉尘 if random.random() 0.2: k random.choice([3, 5]) img cv2.GaussianBlur(img, (k, k), 0) return img3. 模型选型先问要输出什么再问用什么网络3.1 分类、检测、分割三条路线别一上来就上最贵的选型的第一步不是挑骨干网络是确定你要的输出粒度。这三条路线的成本差距能达到十倍以上很多项目死在“明明只需要判有没有却非要上分割”。路线输出标注成本推理开销适用场景图像分类整张图的类别最低只标图级标签极低固定工位、缺陷必定落在视野中心、只需报警不需定位目标检测缺陷框 类别 置信度中需画框中大部分带钢表面检测需要知道位置和尺寸语义/实例分割像素级掩膜最高需描边高需要精确计算缺陷面积、影响判级如夹杂面积占比我的经验是先做分类再做检测分割按需。分类模型可以作为第一级粗筛把“明显正常”的图挡掉只把可疑图交给后面的检测模型整个系统的吞吐能提升五到十倍。而分割只有在客户明确要求“输出缺陷面积用于判级”时才值得上因为像素级标注的成本是画框的三到五倍而且标注一致性更差。检测模型上工程上我更倾向单阶段的 YOLO 系列实现选 n 或 s 这种小模型理由是部署链路成熟、支持动态输入尺寸、导出 ONNX 后量化路径清晰。Faster R-CNN 这类两阶段方案精度在某些小目标场景确实略优但推理链路复杂、后处理里的 NMS 参数在密集小目标上很难调产线上不划算。分割就用轻量的 U-Net 变体或者基于 Transformer 的分割网络前者参数少、对小数据更友好后者在缺陷边界模糊时表现更好但要更多数据。3.2 骨干网络与轻量化的取舍逻辑骨干网络的选型要看你的算力预算和精度缺口。给一组我实测过的数字输入 512×512 灰度图单张 T4 上的推理耗时FP16含后处理骨干参数量单图耗时缺陷召回备注MobileNetV3-Small2.5M2.1 ms86.2%边缘设备首选精度略欠ResNet1811.7M4.8 ms91.5%性价比最高的基线ResNet5025.6M11.3 ms93.1%精度提升边际递减明显EfficientNet-B05.3M5.6 ms92.4%小数据上容易过拟合轻量 ViT 变体5.7M7.9 ms92.8%需要更多数据标注少时别碰从 ResNet18 换到 ResNet50参数量翻了一倍多耗时翻了一倍多召回只涨了 1.6 个百分点。这 1.6 个点在产线上值不值取决于你的 GPU 预算和节拍余量。我的做法是先拿 ResNet18 打到瓶颈如果瓶颈是“模型容量不够”再往上换如果瓶颈是“数据标注质量不行”换再大的网络也是白搭——这一点我吃过亏有次硬上 ResNet101训练集 loss 掉到 0.01验证集纹丝不动问题出在训练集里有一批标签标错了类别。另外要提醒一句工业图像很多是单通道灰度别硬转成三通道喂给 ImageNet 预训练模型就完事。我的做法是保留三通道结构、把灰度值复制三份这样能直接吃预训练权重同时把第一层卷积的权重按通道求平均再复制回去比随机初始化收敛快大概 30% 的 epoch。3.3 细长缺陷和小目标是这类任务的真正难点钢铁缺陷里最难的不是块状缺陷是裂纹。一条长 200 mm、宽 0.2 mm 的裂纹在 0.1 mm/pixel 的图上就是 2000×2 像素长宽比 1000:1。你用什么 anchor 都覆盖不了常规的 3×3 卷积核在感受野里也几乎看不到它。我试过三种解法效果从差到好排列。第一种是加大输入分辨率直接把 512 提到 1024小目标确实好了一些但推理耗时翻了四倍节拍撑不住。第二种是改 anchor 比例加上 1:8、1:12 这种极端长宽比召回涨了 5 个点但对不规则走向的裂纹依然无力。第三种是把图像切成沿轧向的长条 tile比如 512×128专门给裂纹类做一条独立的检测分支和主分支的结果做融合。这个方案召回能到 90% 以上代价是推理要做两次前向。最终我采用的是级联结构主分支跑全图找块状缺陷同时输出一个“疑似细长结构”的掩膜只把这些掩膜区域的坐标送进第二条分支放大重检。综合耗时只增加了 18%但裂纹召回从 71% 提到了 89%。还有一个偏门但特别管用的小技巧在通道维度上叠加梯度幅值图。把原图和它的 Sobel 幅值图堆成两通道输入模型对边缘的敏感度会明显提升尤其是低对比度的浅裂纹。这个改动只增加了第一层卷积的输入通道数几乎不增加计算量。4. 训练与调参那些让你模型“看着能跑其实不能上线”的坑4.1 类别不均衡是所有工业质检的共性难题正负样本比 1:100 是常态某些稀有缺陷能到 1:2000。这时候用普通的交叉熵模型会学到一个“全部判正常”的退化解准确率还有 99%看起来特别漂亮。常规解法是 Focal Loss 或者加权交叉熵但我实测下来在钢铁缺陷上更有效的是难例挖掘 重采样组合拳。具体做法是第一个 epoch 用普通交叉熵把所有样本过一遍然后按每个样本的 loss 排序取 loss 最高的前 20% 正样本和 top 5% 的负样本组成一个“难例池”后续训练时这个池子的采样概率放大 3 倍。Focal Loss 的 γ 参数我会设 1.5 而不是论文常用的 2.0因为工业缺陷的难负样本氧化皮质感本身就很难γ 太大容易把这些难负样本直接放弃掉反而导致过杀率上升。分割任务上Dice Loss 和 BCE 的混合比单用任何一个都稳比例大概 1:1。Dice 负责拉整体重叠度BCE 负责稳住像素级分类的梯度。我在一个夹杂分割任务上试过纯 Dice训练前期 loss 震荡得非常厉害混了 BCE 之后曲线立刻平滑。4.2 超参数不需要玄学按数据量推就行很多人调参靠试我给一套我常用的推算逻辑。学习率用带预训练权重的骨干时backbone 的 lr 设为检测头的 1/10初始值取 1e-3AdamW或 1e-2SGD momentum 0.9。Batch size能塞多大塞多大但因为工业数据集往往只有几千张batch 太大一个 epoch 只有几十步BN 统计量也不稳我一般控制在 1632配合梯度累积模拟大 batch。训练轮次看验证集召回曲线的拐点钢铁缺陷任务通常在 4080 个 epoch 收敛超过 100 还没收敛基本是数据或者标签有问题别硬训。学习率调度用余弦退火 3 个 epoch 的 warmupwarmup 这一条千万别省。工业数据集小开头几步梯度方向噪声很大不做 warmup 很容易一开始就把预训练权重带偏后面怎么训都回不来。我遇到过最典型的一次去掉 warmup 后模型前 5 个 epoch 的 loss 一直在 0.69 附近打转二分类的随机水平加回 warmup 立刻正常下降。import torch, torch.nn as nn from torch.optim.lr_scheduler import CosineAnnealingLR, LinearLR, SequentialLR def build_optim(model, backbone_lr1e-4, head_lr1e-3, warmup_epochs3, total_epochs60): backbone_params, head_params [], [] for name, p in model.named_parameters(): (backbone_params if name.startswith(backbone) else head_params).append(p) opt torch.optim.AdamW([ {params: backbone_params, lr: backbone_lr}, {params: head_params, lr: head_lr}, ], weight_decay1e-4) warmup LinearLR(opt, start_factor0.1, total_iterswarmup_epochs) cosine CosineAnnealingLR(opt, T_maxtotal_epochs - warmup_epochs, eta_min1e-6) return opt, SequentialLR(opt, [warmup, cosine], milestones[warmup_epochs]) # 类别加权按频率的倒数开方避免稀有类权重爆炸 def class_weights(counts, power0.5): inv 1.0 / torch.tensor(counts, dtypetorch.float32).clamp(min1) w inv.pow(power) return (w / w.sum() * len(counts)).clamp(max8.0)注意最后那个clamp(max8.0)这是我自己加的保险。某些稀有类样本只有几十张按倒数算出来的权重能到 50 以上训练直接发散。开方之后再截断是我试下来最稳的组合。4.3 评估指标别只看准确率那玩意儿在工业上会骗人产线关心的指标和学术界完全不是一套。我总结的对照关系是这样漏检率对应召回Recall是红线指标通常要求 99% 以上注意是召回也就是缺陷里被找出来的比例过杀率对应假正率False Positive Rate是成本指标通常要求 5% 以内定位精度用 IoU 0.5 下的 mAP 衡量主要影响后续自动判级响应延迟是硬指标超过节拍就是废的。还有一个特别容易被忽略的指标按卷统计的稳定性。单张图的指标好看不代表一整卷几千米的检测稳定——可能某一段光照变了模型就整段失效。所以我做验收时一定会按卷统计“每千米缺陷数”和“单卷内误报次数的方差”方差大的模型在产线上是不可信的哪怕它的平均指标更好。5. 从实验室到产线部署这一段才是真正的地狱5.1 算力预算要先算清楚再决定模型多大我在第五章开头提过数据量这里把它算完整。假设幅宽 1500 mm精度 0.1 mm/pixel则横向需要 15000 像素用两台 8192 像素的线阵相机拼接覆盖。线速 3 m/s行频 30 kHz。如果按 512×512 的 tile 做推理每个 tile 覆盖 51.2 mm × 51.2 mm那么每秒钟产生的 tile 数是横向 15000 / 512 ≈ 30 列纵向 3000 mm/s / 51.2 mm ≈ 58.6 行/秒合计约 1758 个 tile/秒。就算单张推理只要 2 ms1758 张也需要 3.5 秒的 GPU 时间而实际只有 1 秒。所以你绝无可能对全幅全速做逐 tile 推理。可行的架构只有一种两级筛查。第一级用极轻量的分类器MobileNetV3-Small 级别输入降到 128×128对降采样后的图像做粗筛耗时控制在 0.2 ms 以内理论吞吐能到 5000 张/秒把所有 tile 快速过一遍只保留置信度落在可疑区间的 3%8%。第二级才用高分辨率检测模型处理这些可疑 tile此时每秒只需要处理 50140 张算力完全富余。环节输入模型单张耗时每秒处理量硬件一级粗筛128×128轻量分类0.2 ms5000单张 T4二级精检512×512小目标检测4.8 ms200单张 T4分割可选512×512轻量 U-Net9 ms110单张 T4这套架构还有个额外好处一级粗筛的模型更新频率可以很高因为它训练成本低、对光照漂移最敏感出了新样本一周就能迭代一版二级模型则保持稳定不轻易动。5.2 与产线联动坐标映射比模型本身更容易出错模型输出的是“图上的框”产线要的是“第 3 号卷、距头部 1247.3 米、距操作侧 682 mm 处有一处长 15 mm 的裂纹”。这中间的坐标映射是整个项目里最容易出低级错误的地方而且错了很难发现——因为系统看起来在正常工作只是位置全偏了。映射链路是这样的编码器脉冲 → 相机行号 → 带钢纵向位置相机标定 → 像素坐标 → 横向物理位置再叠加上焊缝跟踪信号扣除活套和张力带来的位置漂移。每一步都要单独验证。我的验证方法很土但有效在产线停机时人为在带钢上贴一张带刻度的标定纸让系统识别并输出坐标然后拿卷尺去量误差控制在 ±3 mm 以内才算过。注意焊缝信号丢失的那几百毫秒坐标会整体漂移缺陷会被算到错误的卷上。这类问题的表现是“某个卷突然报了几十个缺陷、下一个卷干干净净”排查时先看焊缝跟踪日志别一头扎进模型里。推理加速这块路径很标准PyTorch 训练 → 导出 ONNX注意固定输入尺寸动态尺寸会拖慢 TRT 优化→ 用推理引擎做 FP16 或 INT8 量化。FP16 基本不掉精度速度提升 1.62 倍无脑上。INT8 要小心我用 500 张正常图 200 张缺陷图做校准集量化后召回掉了 2.3 个点过杀涨了 1.8 个点最后是“一级粗筛用 INT8、二级精检用 FP16”才把指标捞回来。# 导出 ONNX注意固定 batch1、固定输入尺寸 python export.py \ --weights runs/detect/best.pt \ --imgsz 512 512 \ --batch 1 \ --opset 12 \ --simplify \ --include onnx5.3 现场环境带来的三个“模型之外”的失效点镜头污染是一次缓慢的正弦式衰减。刚擦完镜头那天对比度最好模型表现最佳十天之后整体对比度下降 15%浅裂纹开始漏检。解决办法不是天天擦镜头产线不会给你这个时间窗而是在系统里加一个“图像质量监控”模块实时统计每帧的灰度均值、方差、梯度能量一旦低于基线一定比例就触发清洗提示同时把这段时间的图像标记为“低置信区间”在判级时给一个降级标记。这个功能上线后客户抱怨“系统时好时坏”的声音基本消失了。机械振动带来的是横向像素偏移典型表现是缺陷框在同一个纵向位置上反复横跳。如果你定义了缺陷合并逻辑同一位置的框要去重横向抖动会导致同一个缺陷被算成两个缺陷数量翻倍。我的处理是在后处理里加一个基于纵向距离的聚类纵向间隔小于 20 mm 的同类框合并成一个横向取加权中心。这个简单的后处理让缺陷计数准确率从 82% 提到了 96%。光源频闪与相机行频不同步会产生周期性的明暗条纹这类条纹在某些角度下和辊印高度相似。这种问题必须从硬件上解决——用相机触发信号同步驱动光源不能靠模型去学。我见过一个团队花了两个月调模型想消除条纹影响最后发现是光源驱动器没接同步信号。6. 常见问题与排查速查表6.1 典型故障对照表现象最可能原因排查动作处理方式训练 loss 不下降停在 0.69 附近学习率过大、无 warmup、标签全为同一类打印一个 batch 的标签分布加 warmuplr 降 10 倍检查标签训练集 loss 极低验证集召回很低标签错误、训练/验证集来自不同批次抽 50 张验证集图人工看预测结果重新核对标签按批次划分数据集上线后过杀率突增光照变化、镜头污染、模型与现场成像不匹配对比现场图和训练集图的灰度直方图补现场负样本重训加图像质量监控缺陷位置整体偏移编码器标定错误、焊缝信号丢失用标定纸做坐标验证重新标定加焊缝信号冗余检测同一缺陷被重复计数横向振动导致框分裂统计同一纵向位置的框数量加纵向距离聚类后处理裂纹类长期漏检长宽比过大、输入分辨率不足统计裂纹类召回加长条 tile 分支或梯度通道推理延迟超节拍全幅逐 tile 推理、未做量化用性能分析工具看耗时分布改两级筛查上 FP16/INT8模型版本更新后指标回退新数据集分布偏移、旧难例丢失对比新旧版本在固定测试集上的表现建立固定回归测试集版本灰度的上线6.2 几条用真金白银换来的经验固定测试集必须冷冻永远不许拿去训练。我在项目早期犯过一个错每次补新样本都顺手加进训练集结果验证指标一直涨上线毫无改善。后来才知道我一直在用“见过的题”考自己。正确做法是留一个 5001000 张的固定测试集按钢种、按班次、按月份分层抽样覆盖尽可能多的工况这个集合只在版本发布前跑一次任何情况下都不进训练。模型的版本管理要和生产系统的灰度机制配合。我们现在的做法是新模型先跑“影子模式”——接实时数据做推理但不输出控制信号只在后台记录它和当前生产模型的分歧跑满一周、分歧率稳定在合理区间后才切换。这个机制救过好几次有一次新模型在夜班时段光照条件不同召回掉了 12 个点影子模式直接提前发现了。别忽略“模型能解释”这件事。产线上的班组长不信任黑盒。我们用 Grad-CAM 做了一个简单的热力图叠加缺陷框旁边能显示模型关注了哪块区域。这玩意儿对精度没任何帮助但对项目推进的作用极大——老师傅看到模型关注的地方和他们的判断一致才开始愿意相信系统。技术之外的说服工作往往比调参更耗时间。最后再补一个数据回流的设计。系统上线不等于结束产线每天都会产生新的难例。我们在检测端做了一个“低置信度自动留图”的机制任何置信度落在 0.30.7 区间的样本连同上下文自动存盘并打上时间戳和卷号标签每周由工艺人员复核标注一批回灌进训练集。这个闭环跑起来之后模型的月度迭代基本不需要额外组织采样靠系统自己就能持续变好。这套东西听着简单但真正在产线上跑通从存储带宽、样本去重到标注任务的派发每一步都得设计我花了大概三个月才让它稳定运转起来。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑