☰
华为云ModelArts实践:从数据标注到模型部署的完整链路
2026/10/22 6:30:32 网站建设 项目流程

1. 这个项目到底在做什么,以及我为什么把它记下来

先说个背景。我前后折腾了大概一周时间,把一套图像分类模型从零开始跑通了华为云 ModelArts 的完整链路:数据上传、自动标注、模型训练、部署成在线服务、最后通过 API 完成调用。整个过程记录成了一份学习笔记,这篇博文就是梳理后的版本。

ModelArts 在圈子里不算陌生了,它是华为云上的 AI 开发平台,核心卖点是把数据标注、训练、调参、部署全部收拢到一个界面里。对个人开发者来说,最大的价值不是"它有什么功能",而是"你能不能不看文档、不踩坑,只靠浏览器就把一套模型跑起来"。这篇笔记要解决的问题就是后者——把"从账号到 API 调用"这条链路里的关键决策点、参数含义、容易出错的细节都讲清楚。

适合看这篇内容的人有三类:一是刚接触 ModelArts、想快速跑通一个 Demo 的开发者;二是团队里要评估"要不要把训练迁移到云上"的技术负责人;三是对 AutoML、自动标注这些平台能力好奇、想看看平台层和自建之间有什么区别的同学。我会尽量把每一步为什么这么选、选错了会出现什么现象写出来,尽量少放那种"照着点就行"的没有营养的步骤。

2. 整体链路拆解:数据标注、训练、部署到底是一条什么样的流水线

开始操作之前,我先把整条链路画了一遍。这是我在做这类平台型产品时的一个习惯——先搞清楚数据是怎么流动的,再动手。ModelArts 这条链路大概可以拆成五段。

2.1 数据从哪来、往哪去:OBS 是整个流程的中转站

ModelArts 本身不直接保存你的原始数据,它用的是 OBS(对象存储服务)桶。训练输入、代码包、模型输出、甚至部署时候的模型文件,全部要从 OBS 读或写。这个设计初看有点绕,但实际用起来会发现它很合理:平台本身是无状态的,你的数据资产始终掌握在自己手里。

我的做法是在 OBS 上建了两个桶,实际上一个桶也可以,但两个桶逻辑更清晰:

  • 一个专门放原始数据集,比如图片、标注文件。
  • 另一个放训练输出,模型权重、日志、评估结果都落在这里。

因为计费和清理策略不同,分开管理会让你在排查问题的时候少很多干扰。数据上传推荐用 OBS Browser+ 或者直接拖拽到页面上传,如果数据集规模在几万张图片以上,建议用命令行工具批量传,效率高很多;但如果是几百张图片的演示项目,直接网页拖拽就行,没必要引入额外的工具。

2.2 自动标注能节省多少时间,以及它的边界在哪

我这次用的是图片分类场景,数据集是几百张产品图片,需要区分不同类目。如果手工标注,每张图差不多要用 10 到 20 秒,一百张图就要半小时到一小时,而且眼睛会累,标注质量会下降。ModelArts 的自动标注功能使用了预置模型来辅助标注——你只需要手动标注一小部分,比如各类别先标个十张二十张,平台就会训练一个草稿模型,用它去预测剩余未标注的数据,给出建议标签,你再人工确认或修正。

这个功能的实际体验,我只能说"好用但有边界":

  • 它能大幅加速"预标记"阶段,尤其适合类别之间在视觉上差异明显的场景。
  • 但如果你的类别很接近,比如同一种产品不同颜色的细微差异,自动标注的建议准确率就会明显下降,你需要修改的标签反而比手动标还多。

我用了一个很实际的补充判断:自动标注适合做"粗标",人工确认做"精标",不要把自动标注的输出直接当最终标签用。在标注确认环节,我基本上是全部人工过了一遍,虽然多花了点时间,但这一步直接决定了后面训练效果的上限。

2.3 训练、评估、部署之间的衔接方式

数据到位之后,训练环节用的是 ModelArts 的预置算法加自动调参。训练任务跑完后,模型会被保存到 OBS 的输出路径下。接下来部署环节,你不需要手动把模型搬来搬去,因为 ModelArts 会直接从你的输出路径读取模型文件。

这里有几个选项要提前想清楚:你是要部署成在线服务(按调用次数计费),还是边缘部署(模型下发到设备上离线推理)。我这次是纯在线调用场景,所以选了在线服务。整个过程不需要写服务器代码,也不需要配置负载均衡,平台的模型加载和资源调度都已经封装好了。这一点对于没有后端经验的同学来说上手成本很低,但相应地,部署完成后的排查手段也比自建服务少很多,出现问题时要靠平台的日志和监控逐层定位,后面我会专门讲这个问题。

3. 实操前必须想清楚的三件事:算力规格、算法来源、数据质量

很多人在训练之前会直接冲到"创建训练作业"这一步,结果卡了半天不知道怎么选参数。我总结了三个关键决策点,建议你动手之前就想清楚,选错了后面返工很烦。

3.1 算力规格不是越贵越好

ModelArts 训练作业的算力选择,常见的是 GPU 规格,比如 V100、A800 这一类。公开宣传上数字越大越快,但在真实的使用场景里,对很多人而言,最大的限制其实是每小时费用,而不是训练速度。如果你用的是少量图片做 Demo,一个便宜些的规格跑十几分钟也就结束了,花费完全可以接受;但如果你一开始就选了最高规格,这个项目本来 20 分钟能训练完,费用其实也没差多少。真正费钱的是调试阶段——因为参数没调好,反复跑很多轮,每一轮都在烧钱,规格高的话账单会非常明显。

我的建议是,如果数据集在几千张图片以内,直接选平台里最低档的 GPU 即可;如果数据集是几万张图片,且模型比较大,比如要跑比较深的网络,再考虑更高规格。学会用"最小可行算力"跑通一个流程,再逐步升级,这是云上训练比较省钱的通用思路。

3.2 算法来源:预置算法、AutoML 与自己写脚本的选择

ModelArts 里训练一个模型至少有三种方式:

第一种,直接用预置算法。平台内置了一些常见模型,比如图像分类的 ResNet、目标检测的 YOLO 系、以及一些 NLP 算法。这种方式最简单,参数都已经封装好,你只需要指定输入路径、输出路径和几个超参数即可。

第二种,使用 AutoML 自动学习。它的交互更简单,基本上是把数据集丢进去,平台自动做模型选择和参数搜索。这类功能对非技术背景的用户很友好,但在深度调优的场景下可操控的空间不大。

第三种,自己写训练脚本,然后以自定义镜像或者脚本方式提交作业。这种方式灵活度最高,适合需要特殊网络结构或定制 loss 的场景。

我这次选的是预置算法加少量参数调整,因为项目本身比较小,没必要手写训练逻辑。但你如果有自己的想法,比如想用某个自定义的模型结构,就需要走第三种方式。从成本角度看,预先想清楚自己的算法需求,可以避免在"选择困难"上耗太多时间;从项目的角度看,起步阶段就把算法的设计思路定下来,后面迭代才有明确的目标。

3.3 数据集质量才是真正的决定因素

这可能是整篇笔记里我最想强调的一点。训练作业跑出来效果差,很多人第一反应是"算法选错了"或者"参数没调好",但我遇到过的情况里,相当高的比例问题出在数据。

几种常见的数据问题:

  • 类别不均衡。某个类别图片数量是另一个的十倍,模型会偏向数量多的类,训练出来的准确率很好看,但对少数类几乎失效。先看一眼每个类别的图片数量,再决定要不要做数据增强。
  • 标注噪声。有些标注类的标签本身不一致,同一张图在不同批次标注时被归到了不同类别。这会让模型的收敛过程变得很挣扎,准确率波动也很反常。
  • 图片质量参差。训练集里的图片如果全是官方美图,而实际部署时用户上传的是各种光线下的手机拍摄图,效果会有明显落差。建议在标注阶段就混入一些"脏数据"。

我这次做得比较稳妥的一点,是专门花时间把数据集里明显模糊的、重复的、类别放错的图片清理了一遍。虽然这一遍很枯燥,但它在训练阶段省下的调试时间远超投入。

4. 训练作业的创建与参数配置:从零跑通一次完整训练

接下来的内容,算是手把手级别的实操记录,我会把每一步的关键选项和背后的逻辑都写出来。

4.1 创建训练作业时的核心参数记录

进入 ModelArts 控制台,找到"训练管理"下的"训练作业",点击创建。这里有几个字段值得停下来想一想。

第一个是"算法来源",我选了"预置算法",再选到"图像分类"那一类中的 ResNet 系列。选 ResNet 是因为它在中小规模数据集上的表现比较稳,属于不容易出错的选择。

第二个是"数据来源",需要指定 OBS 路径。这里要注意,ModelArts 的输入路径一般是指向到数据集那一层,而不是具体某个图片文件夹的上级,路径弄错经常会在训练报错时看到一些让人迷惑的错误信息。

第三个是"训练输出",同样选一个 OBS 路径,模型最终会保存到这个路径下面。

第四个是"超参数"。虽然预置算法有一些默认参数,但我建议还是手动确认一遍,常见的几个参数是:

参数名作用我的取值设置逻辑
learning_rate控制模型权重更新的步长0.001数据集规模不大时,太大的学习率容易发散,太小的收敛慢
batch_size每次迭代读取的样本数16显存不是瓶颈,但小 batch 在一定程度上有正则效果
epochs遍历整个数据集的次数50在验证集准确率不再提升时,多跑的轮次没什么收益

我这次的参数序列是跑了三次训练后才确定的。第一轮用默认参数,效果大约 83%,第二轮调低学习率,涨到 88%,第三轮结合数据增强和更长的训练轮次,到了 93% 左右。这个调参过程没有玄学,本质是观察验证集指标变化,然后做单变量调整。

4.2 训练过程中的观测指标怎么看

训练开始后,你会在 ModelArts 的页面上看到日志和指标曲线。我需要提醒一句:不要只看"准确率"这一个指标。在分类任务里,除了准确率,还要关注每个类别的精确率、召回率,特别是类别不均衡的情况下,准确率是一个很具有迷惑性的数字。

我这次就遇到一个很典型的场景:整体准确率 93%,但某个小类别的召回率只有 60%,说明模型对这个类是"漏判"的。这个判断很重要,因为自动调参会以整体指标为目标,但它不会帮你照顾少数类。如果业务上对某个类别有比较高的要求,你就得考虑做类别加权或者收集更多该类别的样本。

至于资源监控,免费的基础监控看 CPU、内存、GPU 利用率就可以了。我发现唯一一次出问题的情况是 GPU 利用率接近 100%,显存占用也比较高,这时就需要考虑是否要降低 batch_size 或者换个更高显存的规格。

4.3 训练完成后的模型管理路径

训练作业到达"运行成功"状态后,模型文件会自动出现在你指定的 OBS 输出路径下。接下来的操作是把模型注册到 ModelArts 的模型管理中。这一步很重要,因为部署在线服务时,平台是通过模型管理来读取模型文件的,而不是直接读取 OBS 路径。

注册模型时,平台会让你选择推理配置,这里一般会对应到预置算法的模型输入输出。选对之后,系统会自动生成一个推理代码的镜像。如果你用的是自定义脚本训练,这一步就需要你提供推理的依赖和脚本了,复杂度会增加不少。

从训练完成到模型注册,整个流程大概十分钟内能搞定。如果你发现模型管理里没有出现,大概率是输出路径没有配置对,建议回训练作业的配置里检查一下输出路径,然后把模型解压出来看看文件结构是否符合平台的预期。

5. 部署成在线服务:从模型到能被外部调用,链路上的每一步

模型注册完成之后,就可以创建在线服务了。在线服务本质上就是平台帮你拉起了一个推理服务,并且暴露一个 API 给你调用。这个环节操作并不复杂,但它是最容易在"可用性"这个细节上翻车的。

5.1 选择服务规格与实例数量

ModelArts 部署在线服务时会让你选择推理规格,常见的是 CPU 和 GPU 两种。很多人会觉得"我用 GPU 训练的模型,推理时也必须用 GPU",这个理解不全对。模型在推理时的计算量远小于训练,对于一些中等规模的模型,CPU 推理也能达到可用状态,只是延迟会高一些。

我的建议是,如果对并发量要求不高、响应时间容忍度在一秒以内,先试 CPU 规格,费用更低;如果试下来延迟不可接受,再换 GPU。实例数量默认是 1,如果你的服务对接的是生产环境,建议至少 2 个实例做冗余,但个人测试环境 1 个就够了。

5.2 模型文件加载失败这类问题的排查方法

部署过程中,我遇到过一个很典型的坑:服务状态显示"异常",日志里提示模型文件加载失败。这类问题的多数原因是模型文件结构与平台预期不一致。

排查思路是这样的:

第一,确认模型文件是否真的在 OBS 路径中,并且没有被防火墙或者权限策略挡住。

第二,确认模型文件的后缀与格式。ModelArts 的预置算法一般产出的是 pb 格式或者平台定义的特定格式,如果你的训练脚本导出的格式不是平台默认的,就需要做转换。

第三,如果模型本身正常,但加载就是失败,建议看一下平台给的错误日志里面的堆栈信息,多数情况下会提示是缺少依赖的 Python 库还是其他问题。

这类问题从经验上看,绝大部分都是"文件路径不对"和"格式不匹配"造成的,排查时先检查这两点,比反复重建服务更高效。

5.3 在线服务调用与鉴权方式

服务部署成功之后,ModelArts 会给你一个 API 地址,也就是推理的请求地址。但这个地址并不是直接裸用的,因为调用需要鉴权。

我的调用方式是:在控制台创建一个访问密钥,或者使用临时密钥,然后在请求头里带上鉴权信息。如果你是用 Python 调用,可以用 SDK 简化这个流程。这里有个小细节,就是请求传入的数据格式。在线服务默认定义的输入是一个 JSON,里面包含图片的 base64 内容,或者图片的 OBS 路径。不同算法对你的输入格式要求不同,建议先用平台的调试功能传一张图片试试,成功后再写正式代码。

我把整个调用过程录入成了一个 Python 脚本,核心流程大致是:读取本地图片,转成 base64,构造请求 JSON,加上鉴权信息,发送 POST 请求,解析返回的推断结果。十几分钟就能完成,而且这个脚本后续换模型、换服务,也只需要改几个参数。

5.4 服务监控与成本控制

部署完成不是结束,还要看一眼平台的监控。ModelArts 在线服务有基本的调用量、错误率、平均延迟这些指标,一定要养成看这些数据的习惯。

成本控制方面,我的经验是,在线服务是按实例规格和运行时长计费的,如果你只是测试一下,用完就删掉服务,别一直挂着。我见过不少开发者因为忘了删除测试服务,一个月后账单多出几十到上百块钱,这种开销其实完全可以避免。

6. 实操中遇到的几个坑和解决办法,按排查顺序整理

这一节写的全部来自我自己踩过的坑,按时间顺序排一下,方便你对照着排查。我尽量写的具体一些,因为这种问题在官方文档里往往是分散的,真正遇到的时候很难搜到一起。

6.1 数据路径分隔符导致的读入失败

第一次跑训练作业时,我指定的路径是obs://bucket/data/图片数据/,想着平台能够自动处理,结果提示路径无效。问题出在 OBS 的路径规则上,即便是在 Windows 本地习惯了反斜杠,到了 OBS 上也应该统一用正斜杠,而且路径里最好不要有中文。把桶名、路径改成英文,重新指一下路径,问题马上消失。虽然这个错误很初级,但不少人不注意,第一次就在这卡住了。

6.2 预置算法版本与界面选项不一致

ModelArts 平台的版本迭代很快,有时候你在某篇旧教程里看到的算法名称,在当前控制台里已经找不到,或者换了个入口。这不是你的问题,也不是教程的问题,而是平台升级导致的。应对方法是尽量以当前控制台的选项为准,把搜索框的关键词换成算法类型而不是具体名称,比如搜"图像分类",而不是搜某个具体的模型名。

6.3 训练日志提示显存不足

关于显存不足,先说结论:多数情况下和代码没关系,就是规格的显存装不下当前的 batch_size 和模型。我遇到过几次,处理方法很直接:先把 batch_size 减半,不行就换更高规格的算力。如果是自定义脚本,还要检查代码里是否有显存峰值控制逻辑的问题。平台日志里一般会直接写明哪类资源不够,看到Out of memory之类的关键信息时,不要觉得是自己代码写错了,先改资源配置和 batch_size。

6.4 在线服务测试时返回 401 鉴权失败

部署好的服务,第一次用脚本调用时,返回了 401。这个错误本质是请求头里的鉴权信息没有被正确识别。我在排查时确认过几件事:一是访问密钥是否有效,二是不是临时密钥过期,三是请求的签名信息是否按平台规则生成。如果你和我一样用的是 SDK,只要按照 SDK 的文档重新生成一下客户端对象就行,一般不会有大问题。自己拼 HTTP 请求时,签名算法比较繁琐,建议优先用 SDK。

6.5 模型效果与训练时相差过大的排查方向

模型训练时验证集准确率 93%,到了在线服务里测试却明显下降,这种情况比较常见。原因基本集中在数据预处理不一致上。训练时平台会做一些数据增强,比如裁剪、翻转,但推理时如果你的输入图片没有做同样的预处理,模型的效果就会被影响。我当时的解决办法是确认推理请求中传入的图片格式与训练时一致,如果训练时统一用了某个尺寸,推理时也要统一。对于预置算法,这一点通常封装好了,但你自己处理图片时很容易忽略。

6.6 从日志信息到问题定位的习惯

把以上几个问题汇总后,我比较深的体会是:排查问题要优先看日志,但也不是什么日志都看。先看任务的启动日志,也就是最前面那一段,平台会打印出环境信息、依赖安装情况、数据加载情况。然后看训练日志里的 loss 曲线和指标输出,确认是不是训练过程的异常。最后再看部署日志,定位推理时的问题。这个顺序可以避免你在错误的方向上浪费大量时间。

7. 从学习笔记到可落地的小经验

把整条链路跑通之后,我回头整理了一下哪些经验在后续的项目迭代中也能复用。

第一条经验是一定要用版本化的方式管理数据集和模型输出。我在 OBS 上给每次训练都建立了独立的输出目录,比如output/train_001、output/train_002。这样做的好处是,当你想回到上一版模型去做对比时,不需要重新训练,直接部署旧输出路径就行。如果你每次都是覆盖同一个路径,前面的成果很容易被冲掉。

第二条经验是学会用平台提供的自动化和策略能力。ModelArts 是支持一些自动化的,比如定期触发训练、模型版本管理、监控告警。对于一个小团队来说,这些能力能省下不少人力。但也不建议一开始就把这些全部配齐,先把基础链路稳定下来,再逐步加策略。

第三条经验是"成本意识"要前置。很多人在云上做项目,只关注效果,不关注账单。等到月底收到账单才开始焦虑。我的习惯是每次创建训练作业前先估算一下费用,训练过程中留意一下运行时间,部署完测试结束后及时释放资源。这个习惯长期下来能帮你省下不少开销。

第四条经验是文档的更新速度追不上平台的变化,写学习笔记不要只记录"点了哪个按钮",而是记录"这一步要解决什么问题"。因为按钮的位置可能会变,问题本身却不会。这份笔记我在写的时候也刻意保持了这种风格,希望你在看的时候,重点不是模仿我的操作路径,而是理解每条路径背后的判断逻辑。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询