用 SageMaker 管理千级摄像头专属模型
参考架构基于 SageMaker SDK v3,为每台摄像头分别训练、质量检查、编译并管理模型版本。通过 SageMaker Neo 和 Step Functions,在账户配额内调度大规模重训练。
AI 深度解读
一台相机的质检模型跑通以后,真正的难题才开始:产线扩到 40 条,每条还有多台相机,角度、反光和光照都不同。AWS 这篇文章讨论的,是怎样把按相机训练、验收、编译和登记模型,变成一套能批量运转的流程。
作者给出的结论是:用 SageMaker SDK v3 组织训练,用质量门槛拦住不合格模型,再用队列和并发控制安排整个设备群的重训。它值得读的地方,是把模型之外容易遗漏的交付细节串了起来;但低成本跑通示例,距离验证生产效果还有一段路。
为什么每台相机都要保留自己的模型历史
作者在参与过的生产部署中发现,把所有相机的画面混在一起训练,得到的模型在部分相机上表现不足,最后仍需逐台微调。这是文章采用「每台相机一套模型」的经验依据,原文没有提供统一模型与独立模型的对照数据。
训练入口共用一个 SageMaker Pipeline,通过相机参数区分任务,每次执行包含 13 个步骤。Preprocess、Fetch Latest Anomaly、Fetch Latest Classifier 并行启动,分别处理数据、寻找两个分支最近获批的模型。
两个分支各有用途:小型卷积自编码器学习正常产品的样子,通过重建误差发现异常;使用 ImageNet 权重微调的 ResNet18 分类器判断缺陷。异常检测负责发现偏离正常的画面,分类器负责学习已有标签对应的区别。原文没有展开设备端如何组合两者的判断。
模型登记到两个共享的 package group,靠 customer_metadata_properties 中的 CameraId 区分相机。每次重训只接续这台相机自己的历史;首次运行时,分类器从 ImageNet 权重开始,自编码器随机初始化。
这里有个扩展成本:ListModelPackages 无法在服务端按客户元数据过滤,查询步骤需要按时间倒序翻页,直到找到目标相机的模型。目录能统一管理,不代表查询成本不会增长。
模型过关,为什么不能只看准确率
示例约 90% 的图片是正常品。模型全部预测为正常,accuracy 也能达到约 0.9,却漏掉所有缺陷。
因此,异常检测分支要求 AUROC 至少为 0.8;分类分支同时要求 balanced accuracy 至少为 0.6、defect recall 至少为 0.5。前者是各类别召回率的平均值,后者直接检查缺陷到底找回多少。
双门槛有明确理由:正常品召回率为 1.0、缺陷召回率只有 0.2 时,balanced accuracy 仍能达到 (1.0 + 0.2) / 2 = 0.6,单看它还不够。
下面这段代码把两个指标同时接入注册前的检查:
step_check_classifier = ConditionStep(
name="CheckClassifierQuality",
conditions=[
ConditionGreaterThanOrEqualTo(
left=JsonGet(
step_name=step_eval_classifier.name,
property_file="evaluation",
json_path="balanced_accuracy",
),
right=min_accuracy,
),
ConditionGreaterThanOrEqualTo(
left=JsonGet(
step_name=step_eval_classifier.name,
property_file="evaluation",
json_path="defect_recall",
),
right=min_defect_recall,
),
],
if_steps=[step_compile_classifier, step_register_classifier],
else_steps=[step_fail_classifier],
depends_on=[step_eval_classifier],
)
要看的是 conditions 和 if_steps:ConditionStep 要求条件全部成立,通过之后才允许编译、注册。阈值是 pipeline 参数,每次执行都能调整,无须重新部署。失败时,FailStep 标记执行失败,该分支不会登记新模型;两个分支独立检查,另一分支仍可能登记成功。
训练侧则用 WeightedRandomSampler 按类别频率的倒数抽样,损失函数保持不加权。作者提醒,同时加权抽样和损失,可能过度偏向少数类。
验收对象应当是准备交付的产物。
两个分支都先导出 ONNX,再用 ONNX Runtime 跑留出数据评估,避免 PyTorch 内存模型表现正常、导出文件却有问题。但这套门槛只评估了 ONNX,后续 Neo 编译产物的数值一致性和设备端性能验证,原文没有交代。
从通过评估到设备可用,中间还有哪些坑
这套更新方案用 SageMaker Neo 替代已经弃用的 SageMaker Edge Manager,固定执行「检查、编译、注册」的顺序。只有编译成功,模型才能成为 Approved package。
编译步骤处理了三件具体的事:训练输出的 model.tar.gz 混有检查点和指标,需要重新打包成只含 ONNX 模型的压缩包;导出使用动态 batch 轴,而 Neo 需要确定形状,所以编译请求固定 batch size 为 1;编译任务名由执行 ID 确定,步骤重试时继续轮询已有任务。
NeoTargetDevice 可选择 jetson_xavier 或 rasp4b,默认按 NeoTargetOs/NeoTargetArch 的 LINUX/X86_64 编译。Model Registry 保存可移植的 ONNX,S3 保存含 compiled.so 的优化产物,由 DLR runtime 加载。Neo 编译本身不收费,驱动它的 processing 实例和 S3 存储仍计费。
这还不是完整的设备发布系统。注册条目的容器引用是训练镜像,不提供推理服务,也不是供 CreateEndpoint 使用;把文件分发到设备,仍需接入工厂现有机制。
批量重训由 SQS FIFO、Lambda 和 Step Functions 串起来,DynamoDB 信号量默认最多放行 5 个 pipeline execution,避免 500 个请求同时启动。关键在于原子更新,而不是先读计数再决定:
acquire_semaphore = tasks.DynamoUpdateItem(
self, "AcquireSemaphore",
table=semaphore_table,
key={"LockName": tasks.DynamoAttributeValue.from_string("pipeline-concurrency")},
update_expression="SET ActiveCount = if_not_exists(ActiveCount, :zero) + :one",
condition_expression="attribute_not_exists(ActiveCount) OR ActiveCount < :limit",
)
要注意 condition_expression:检查上限和增加计数在同一次操作里完成,消除了读写之间的竞争窗口。所有失败路径还必须释放名额;完成通知走 SNS,运行故障经 EventBridge 转发到同一主题,并保留原始错误。
部署也有 SDK v3 特有的前提。sagemaker>=3.0.0,<4 拆分为 core、train、serve、mlops 等包,训练改用 ModelTrainer 和类型化配置。SDK 在 CDK 合成阶段就校验真实 IAM role,因此要先用 cdk deploy SageMakerCVPipelineStack -c bootstrap=true 创建角色、bucket 和 ECR,再执行 cdk deploy --all。这里的上下文参数与每个账户、Region 执行一次的 cdk bootstrap 是两回事。
执行角色 ARN 必须是具体字符串。作者还发现,v3 校验 ECR 拉取权限时不带资源 ARN,导致仅授权单个仓库的角色无法通过校验,示例因此扩大了 ECR 授权范围。
运行环境要求 Python 3.10、3.11 或 3.12、Docker,以及 AWS CDK CLI 2.1131.0 或更高版本。跨 Region 部署时,应在命令前同时指定三个变量:AWS_REGION=us-east-2 AWS_DEFAULT_REGION=us-east-2 CDK_DEFAULT_REGION=us-east-2 cdk deploy --all,避免 CDK、Boto3 和 AWS CLI 解析到不同区域。
我的判断
我认可这套方案把质量检查、产物编译和运行故障处理放进同一条链路。它解决的是能否持续交付的问题,对已经使用 AWS、确实需要逐相机微调的团队很有参考价值。
但阈值只是示例参数。缺陷召回率 0.5 能通过检查,不代表业务能接受漏掉一半缺陷;原文也没有提供真实工厂数据证明这些阈值足够。
成本同样需要限定范围:作者报告,合成数据完整运行 13 步、包含两次 Neo 编译,约需 15 分钟,计算费用约 $0.07。这是 2026 年 7 月 us-east-2 按需 ml.m5.xlarge 计费条件下的结果;样例规模的编排资源每月远低于 $0.10,不能据此推算整个工厂的费用。
BCCD 示例只有 364 张血液涂片图像,以是否出现血小板模拟缺陷,能验证流程通路,不能证明工业质检效果,更不是临床结论。作者也提到,需求若能被 Amazon Lookout for Vision 等托管方案满足,可以选更简单的路径;原文没有提供这些替代方案的效果、成本对照。
能拿来做什么
- 做少数类识别任务时,可以借鉴「balanced accuracy 加少数类 recall」的验收方式,再按漏检成本设置阈值,避免被总体 accuracy 误导。
- 维护导出和部署流程时,可以先评估 ONNX,再编译目标设备产物,并补上编译后的推理验证,让验收覆盖实际交付链路。
- 用 Node 或其他服务接收批量训练请求时,可以借鉴队列加原子信号量的设计,同时落实失败释放和错误通知,避免任务占满名额后长期阻塞。
- 准备迁移 SageMaker SDK v3 时,可以先验证 IAM 合成期校验、ECR 权限和 Region 配置。清理示例时还要先删除运行期创建的 model package,再执行
cdk destroy --all -c bootstrap=true --force。