从零开始用ModelArts跑通云上图像分类训练与部署

发布时间:2026/10/22 16:00:04
从零开始用ModelArts跑通云上图像分类训练与部署 两年前我第一次在本地跑深度学习模型光是配置环境就让我怀疑人生。显卡驱动装完CUDA版本不匹配PyTorch装好了又是cuDNN的问题最后模型还没开始训练周末已经结束了。后来因为做一个图像分类的项目我开始尝试基于华为云ModelArts完成模型训练与部署整个流程从“折腾环境”变成了“专注模型本身”。这篇学习笔记是一份面向零基础的实操记录不追求把每个原理讲到多深重点是讲清楚每个环节需要做什么、为什么要这么做、怎么避免踩坑适合刚接触云上AI训练的开发者也想分享给那些打算快速把模型落地的学习者。1. 为什么最终选了ModelArts一次方案选型记录1.1 本地训练解决不了的三件事在我一开始的思路里训练模型就是“在本地写好代码跑GPU”。但实际做下来本地训练有三个绕不开的痛点。第一是环境依赖。Conda可以帮你隔离Python包但底层那些库比如CUDA、cuDNN、NCCL只要显卡驱动升级一次之前能跑的代码可能就再也跑不起来了。有一回我把驱动从老版本升到新版本好几个项目的训练直接报segmentation fault查了半天才发现是新驱动和旧cuDNN不兼容。这件事让我意识到环境问题有时候比算法问题更耗时。第二是算力资源。我手头只有一张消费级显卡显存有限大一点的模型和数据集根本塞不下。有人会说“那租服务器啊”但自己租云服务器开GPU实例又能怎样装环境、配网络、管理数据每一件事都要亲力亲为而且训练完如果忘了关费用照样在烧。第三是“训练出来不等于交付”。模型训练完只是得到一个权重文件要把它变成真正能给别人调用的服务还得自己写HTTP接口、做权限校验、写文档、配置反向代理。对一个小项目来说这部分工程成本有时比训练本身还高。1.2 ModelArts解决这些问题的方式大概是被这些问题折磨得够呛我开始研究云厂商提供的一站式AI平台。ModelArts给我的第一感觉是“它把AI开发流水线化了”数据传到OBS训练作业跑在GPU集群上训练结果自动落到模型仓库再一键部署成在线服务。你可以在一个控制台里完成从数据到API的全部闭环省掉了大量“环境工程”。更深一层看它带来的不是“买了一台远程GPU”而是一套完整的开发范式。数据处理有数据集管理调试有Notebook正式训练有训练作业部署有模型管理和在线服务。这些模块之间天然衔接你在Notebook里写好的训练脚本可以直接提交成训练作业训练作业输出的模型目录可以直接注册成模型版本模型版本又可以部署成服务。每一步都踩着前一步的结果走不用来回导文件、传压缩包。顺带提一句ModelArts的自动学习这是我印象很深的功能。它本质上把选模型、定超参、调优这些事打包成一个自动化流程你只需要给数据打标系统自动训练出模型并部署成API。虽然它的上限受限于内置算法但对新手建立“从数据到部署”的全局认知非常有帮助。我自己是先跑通了自动学习才有信心去写详细训练脚本。这里有必要提醒你自己判断一下如果你只是偶尔跑个实验不追求工程化交付那本地环境折腾一次也无妨。但如果你是打算认真做一个能持续迭代的项目ModelArts这种全流程平台确实能把很多“脏活累活”挡在门外。1.3 核心概念速览先搞清楚这些名词很多人第一次打开ModelArts控制台会有点懵因为“数据集”“Notebook”“训练作业”“模型管理”“在线服务”一排菜单看起来像五个不同的产品其实它们是一条流水线OBS底层对象存储数据都放这里。可以把它理解成“能配合计算集群高速读写的云网盘”。数据集ModelArts对OBS数据做的结构化描述包括标注信息和数据集类型。Notebook云上Jupyter环境适合数据探索、代码调试、跑小实验。训练作业把数据、代码、资源配置一起提交在GPU集群上执行训练任务。模型管理管理训练产物权重、配置文件、推理脚本记录不同版本。在线服务将模型发布成可调用HTTP接口的推理服务也是最终交付形态。如果把这几个概念对应到开饭店OBS是仓库存食材数据集是菜谱清单什么菜配什么料Notebook是厨房小灶试验新菜训练作业是标准化大厨批量做菜模型管理就是菜单记录能提供什么菜在线服务则是端给客人的成品。这样记起来轻松很多。2. 训练前的准备数据规划和环境铺垫2.1 先想清楚数据放哪里OBS桶规划我这次做的模拟项目是一个花卉图像分类Demo目标是把照片按品种分出来。在开始训练之前第一步不是写模型代码而是去OBS规划数据存储。为什么要用OBS而不用普通服务器磁盘因为训练作业跑在集群上训练节点是不固定的你不可能要求它访问某台服务器的本地盘。OBS是对象存储集群可以同时从它那里读取数据训练结束后结果也能直接回传OBS。这一步相当于把数据和计算解耦了。实际操作中我把桶名规划成英文小写加横线风格类似demo-flower-classification桶里目录结构分成两类demo-flower-classification/ ├── data/ │ ├── train/ │ │ ├── daisy/ # 每类一个文件夹 │ │ ├── rose/ │ │ └── sunflower/ │ └── val/ │ ├── daisy/ │ ├── rose/ │ └── sunflower/ └── output/ # 训练输出目录由训练作业自动填充这种按类目分文件夹的布局非常直观因为ModelArts的自动学习和很多预置算法都支持“目录名即标签”这种组织方式。如果你做目标检测或语义分割通常还要准备标注文件但那属于另一个方向这里先不展开。上传数据时我建议优先用命令行工具obsutil而不是控制台拖拽。几百张图片手动传没问题一旦到了几个GB控制台界面很容易卡死。用obsutil批量上传的体验顺畅得多# 假设登录配置已完成 ./obsutil cp ./local_images/ obs://demo-flower-classification/data/ -r -f这条命令把本地目录递归复制到OBS桶obsutil本身支持断点续传传大文件时网络中断了重新执行一次它会接着传。注意-f表示强制覆盖如果你想保留OBS里已有的同名文件去掉这个参数会更安全。2.2 数据质量和标注要提前重视训练效果好不好很大程度上取决于数据质量这个道理每个人都知道但真的轮到自己整理数据时才体会得到。我在项目中重新整理过一批花卉图片踩到的第一个坑是训练集里某一类图片全是高清大图、另一类又是模糊小图导致模型很容易偏向数据量多的类别。后来把每类图片数量均衡到差不多的水平并做了一遍基本清洗去掉损坏文件、去掉标签错误的样例、压缩掉极端尺寸的图。对于入门练手ModelArts也提供了一些示例数据集比如常见的手写数字识别数据。完全没必要一开始就自己爬数据先用公开数据集跑通全流程再换自己的数据这样出问题时更容易定位。如果是自建数据做图像分类标注时这几点值得留意类别命名统一不要一会儿rose一会儿roses-flower训练集和验证集从同一个数据源里拆分避免类别分布差异过大图片格式统一最好预处理成相差不大的分辨率减少训练时解码开销类别数量控制在个位数以内方便新手阶段分析错误。2.3 训练规格别一上来就开最贵的GPUModelArts创建训练作业时会让你选择资源规格CPU、GPU、Ascend都有。我的原则很朴素先用小规格跑通流程确认代码没问题再用大规格做正式训练。第一次跑训练作业时我选了一个基础CPU规格。虽然速度慢但能把“数据读取→模型定义→训练循环→保存模型”这条链路验证一遍。确认这整条链路没问题后再换成GPU规格做正式训练。为什么不建议一上来就用大规格因为训练脚本本身很可能有bug数据路径写错、维度对不上、预处理漏了归一化这些错误在CPU上几十秒就暴露了。如果一开始就用贵的GPU节点报错了一样要排错但账单按GPU计费成本完全没必要。先小后大是控制时间和费用最直接的手段等脚本稳定了再上大算力效率反而更高。3. 训练实操我跑通一个图像分类模型的完整过程3.1 先用自动学习建立基线这是我很推荐的第一步尤其是第一次接触ModelArts的人。自动学习对数据的要求极低把标注好的图片导入数据集选“图像分类”然后点“开始训练”平台就会自动完成特征提取、模型训练、评估一整套工作。我用的自动学习流程大致是这几步在控制台进入“自动学习”创建“图像分类”项目关联数据集选择之前传到OBS的花卉图片配置训练类型为模型训练提交任务等作业跑完平台给出准确率等指标如果效果满意可以直接一键部署成在线服务。自动学习跑出来的模型精度不会特别极致但它给了你一个baseline。如果后面自己写代码连这个基线都打不过那多半不是算法的锅是代码有bug。以后的实践中你可以把自动学习当成一个快速验证数据和业务可行性的工具而不是依赖它出最终成品这是我个人的真实感受。3.2 Notebook调试把本地思路搬到云端自动学习跑通之后我开始在Notebook里写自己的训练脚本。ModelArts的Notebook本质上是云端Jupyter环境创建实例时可以选择不同的AI镜像比如PyTorch、TensorFlow等镜像里已经预装了框架和驱动不用自己再折腾环境。我习惯先用Notebook做小规模代码验证写一个最简训练脚本import torch from torch import nn from torch.utils.data import DataLoader from torchvision import datasets, transforms device torch.device(cuda if torch.cuda.is_available() else cpu) transform transforms.Compose([ transforms.Resize((224, 224)), transforms.ToTensor(), ]) dataset datasets.ImageFolder(data/train, transformtransform) loader DataLoader(dataset, batch_size32, shuffleTrue) model nn.Sequential( nn.Conv2d(3, 16, 3, padding1), nn.ReLU(), nn.MaxPool2d(2), nn.Conv2d(16, 8, 3, padding1), nn.ReLU(), nn.Flatten(), nn.Linear(8 * 112 * 112, 3), ) optimizer torch.optim.Adam(model.parameters(), lr1e-3) for epoch in range(3): for images, labels in loader: images, labels images.to(device), labels.to(device) outputs model(images) loss nn.CrossEntropyLoss()(outputs, labels) optimizer.zero_grad() loss.backward() optimizer.step() print(fepoch {epoch}: loss {loss.item():.4f})这一段代码不复杂但验证了“网络能跑起来”“数据能被正确读取”“训练循环没问题”。跑通之后再把它扩展成更完整的训练脚本然后把本地路径改成从环境变量读取准备提交到训练作业。3.3 从Notebook到训练作业路径与超参必须可配置训练作业和Notebook的最大区别是Notebook是交互式调试训练作业是提交一个任务由平台调度集群去执行。因此训练脚本不能把路径写死必须支持从外部注入数据路径、输出路径和超参数。训练作业的运行机制是你在控制台填的参数会以环境变量的方式注入到训练容器里。所以训练脚本的正确打开方式是使用argparse或os.environ读取import argparse import os parser argparse.ArgumentParser() parser.add_argument(--data_url, typestr, defaultos.environ.get(DATA_URL, ./data)) parser.add_argument(--train_url, typestr, defaultos.environ.get(TRAIN_URL, ./output)) parser.add_argument(--epochs, typeint, default20) parser.add_argument(--batch_size, typeint, default32) parser.add_argument(--lr, typefloat, default1e-3) args parser.parse_args()我在模拟项目中创建训练作业时填的参数类似这样配置项填写值数据来源obs://demo-flower-classification/data/训练输出obs://demo-flower-classification/output/算法来源自定义训练脚本资源规格GPU单卡learning_rate0.001batch_size32epochs20提交之后平台会把数据集挂载或拷贝进容器并把超参数传给脚本。整个训练过程中的stdout和stderr日志会实时出现在训练作业详情页每次打印epoch的loss我都能在后台看到感受和本地训练几乎一样。这里有一个关键细节训练结束后记得把模型保存到train_url指定的目录例如torch.save(model.state_dict(), os.path.join(args.train_url, model.pth))。训练作业执行完成后这个目录下的所有文件会自动同步回OBS后续部署才拿得到权重。我一度忘了加这行代码结果训练作业显示成功OBS里却什么都没有这种低级错误真的比模型不收敛更容易犯。3.4 监控训练不只是盯loss训练作业跑起来之后如果只盯着loss值很容易被它的起落干扰。我的小经验是看日志时至少关注三个信号数值是否趋于下降、早期是否有显存错误、训练速度是否异常。日志里出现类似下面的输出就是健康状态epoch 0: train loss 2.0198, val_acc 0.3412 epoch 1: train loss 1.5234, val_acc 0.5276 epoch 2: train loss 0.9012, val_acc 0.7341如果loss一直卡在某个值来回震荡不下降我一般先想到学习率是不是开太大或者数据归一化没做。如果出现CUDA out of memory基本是batch size太大或显存放不下。先跑小batch调试确认逻辑无误后再增大batch size这是我常用的套路。想更进一步训练作业的输出目录还可以输出TensorBoard的events文件只要写到OBS再通过Notebook读取就能画更精确的训练曲线。但这一步属于锦上添花先能把loss和accuracy输出到标准日志已经解决了“盲训练”的大部分问题。4. 部署上线从权重文件到可调用的在线服务4.1 先理解ModelArts的模型包长什么样训练结束不等于项目交付。ModelArts里的“模型”不是一个裸的.pth或.h5文件而是一个带有推理逻辑和描述信息的模型包。一个最简单的模型包目录结构是这样的model/ ├── config.json # 描述模型元信息 ├── model.pth # 训练得到的权重文件 ├── customize_service.py # 自定义推理脚本 └── variables/ # 其他资源文件如有其中config.json是平台识别模型的关键里面至少要说明模型格式、推理接口等信息我当时的写法类似这样{ model_algorithm: image_classification, model_type: PyTorch, apis: [ { protocol: http, url: /, method: post, request: { Content-type: application/json } } ] }customize_service.py里定义真正的推理逻辑因为不同任务的输入千差万别平台需要一个脚本知道“收到的请求怎么变成模型输入”“模型输出怎么变成用户友好的返回”。示意代码大概是下面这个风格import torch from PIL import Image from torchvision import transforms model None def _preprocess(data): image_bytes data[image_base64].encode(utf-8) # 解码、缩放、归一化等 return tensor def _inference(input_tensor): with torch.no_grad(): output model(input_tensor) return output def _postprocess(output_tensor): idx output_tensor.argmax(dim1).item() return {category_id: idx, label: class_names[idx]}这里只是示意实际运行时函数签名和返回值要以平台当前版本为准。作为初学者最需要注意的是推理脚本里写的输入字段要和你最终调用API时传的字段保持一致否则服务是通的数据却解析错误。4.2 创建模型版本与在线服务权重文件在OBS里、模型包也准备就绪后就可以去“模型管理”里创建模型。模型创建好之后下一步是部署在线服务。部署时要选资源规格和实例数量。最基本的方式是选一个GPU实例把实例数设为1。点击部署后平台会启动一个推理容器拉取模型包、加载权重、启动HTTP服务。整个过程通常需要几分钟状态从“创建中”到“运行中”看到“运行中”就说明服务已经就绪。这里要给一剂镇定药第一次部署时服务状态可能会卡在“创建中”比较久别急着反复删除重建先看部署日志。很多部署失败在日志里都能看到原因比如模型包路径错了、config.json格式不对、依赖的Python包缺失。学会看部署日志排查速度会快很多。4.3 调用在线服务一个POST请求的事部署成功的在线服务会提供一个调用地址通常是一个HTTPS端点。用Python请求这个服务非常简单把图片转成base64字符串放进JSON里POST过去import base64 import requests with open(test_image.jpg, rb) as f: img_b64 base64.b64encode(f.read()).decode(utf-8) resp requests.post( https://你的服务调用地址/v1/infers, headers{Content-Type: application/json}, json{image_base64: img_b64}, timeout10, ) print(resp.json())返回结果通常是一个JSON对象里面包含你在_postprocess里定义的字段比如类别ID和标签。我在模拟项目里拿了几张没参与训练的图片测试模型能正确区分出菊花、玫瑰和向日葵。虽然个别模糊图还是会错但对这个练手项目来说已经完整走通了“训练→部署→调用”这条链。4.4 部署层面的几个进阶能力这里偏个题说点进阶的如果真正有业务诉求ModelArts在线服务还支持自动伸缩、灰度发布、AB测试、监控告警这些能力。自动伸缩的意思是平时可以只保留一个实例等请求量上来了系统自动扩容结束后再缩回来。这个机制能有效控制成本但初学阶段尽量先专注把基础部署跑通不要一上来就开太多功能否则出了问题会不好定位。5. 踩坑记录与问题速查我从实战里攒下的经验5.1 显存溢出CUDA out of memory这个问题遇到次数非常多尤其在GPU训练时。常见原因有三个batch size设置过大、输入图片分辨率过高导致中间特征图占大量显存、模型本身规模超出容器分配到的显存额度。解决方向很直白先把batch size从64降到16试试还报错就检查输入图片尺寸是不是被放大到不合理的值再不行就换一台更高显存的规格。显存溢出其实是最友好的错误因为它是直接报错不会让你在错误结果里瞎猜。5.2 训练作业显示成功但没产出模型这是我说的那个“低级但高发”的问题。训练日志没有报错结束状态是“成功”但看输出目录却是空的。原因基本只有一个代码里没有把模型权重保存到train_url路径或者保存路径写错了训练结束后文件没同步回OBS。排查方式很简单打开训练作业详情页的日志看最后几行有没有类似“saving model to”的打印。如果没有说明代码里压根没执行保存逻辑。在训练脚本末尾加上torch.save并确保保存路径来自外部传入的train_url即可。5.3 部署时服务一直异常日志提示权重文件找不到模型部署时平台会把模型包从OBS下载到推理容器。如果config.json里写的模型文件名和模型包里的实际文件名不一致启动加载时就会报“model file not found”。这里要特别注意模型包目录中权重文件名要与config中声明一致不要出现配置里写model.pth、实际文件叫best_model.pth的情况。这种问题在创建模型时通常不会前置拦截只有部署后看日志才能发现。5.4 数据读取慢导致训练时间异常长训练作业跑起来后每个epoch的间隔越来越长很可能是数据在不停地从OBS下载、实时解码IO出现了瓶颈。处理方法主要有把数据集提前拷贝到容器本地目录再训练或者把大量小图片合并成统一的数据格式减少小文件数。小文件一多读取特别慢这个坑在真实项目里非常常见。5.5 成本控制忘记释放资源是最贵的教训云端的GPU是按时间计费的我身边有伙伴在线服务开了三四天没关月底账单出来吓一跳。训练作业跑完就结束不需要单独释放但在线服务这类常驻资源一定记得在不用时点击停止。我自己定的规矩是每次用完在线服务立刻停止训练作业只在需要时提交Notebook不长时间挂在后台。控制台里定期刷新资源统计确认没有隐藏的扣费资源。论重要性这条比前面任何一条技术排查都值得更新到自己的清单里。常见问题现象可能原因解决方法CUDA out of memory训练中途报错终止batch_size过大或模型显存超限降低batch_size / 减小输入分辨率 / 换更大规格训练成功但无模型输出OBS输出目录为空代码未保存模型或路径错误在训练脚本末尾用train_url保存权重部署服务一直异常实例反复启动失败config.json路径或格式错误核对模型包文件名与config声明一致数据读取极慢epoch间隔很长OBS上的小文件过多本地缓存数据或合并文件再训练调用API返回解析失败响应不是预期JSON输入字段和推理脚本不一致对齐请求字段与_preprocess中的解析逻辑这篇学习笔记写到最后聊几句个人体会。云上AI平台确实把环境和运维藏了起来但“藏起来”不代表“不花钱”也不代表“不需要懂模型”。我最大的感觉是成功跑通一次训练和部署之后真正留下的不是那个权重文件而是你对整套流程的心智模型——你知道数据在哪、作业怎么提交、日志怎么看、服务怎么调、资源怎么停。有了这套心智模型换任何平台和框架都不慌。最后给刚入坑的开发者一个小建议先从自动学习和公开数据集做起一次只改一个变量跑通比跑得快重要得多。训练脚本里的路径问题、保存模型问题、资源释放问题这些看似小的细节反而决定了你能不能走完全程。祝你的第一个云端模型一次成功。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询