多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

从零搭建AI工程:从模型训练到上线部署的完整路线图

从零搭建AI工程:从模型训练到上线部署的完整路线图 最近不少人问我同一个问题现在到处都在谈AI工程手上也攒了不少模型训练的demo可真到了要把AI能力变成一个能上线、能维护、能迭代的产品时总觉得隔着一层窗户纸。市面上讲算法理论的课程一大堆讲Hello World级项目的手把手教程也不少但那种从零开始一点点把AI工程化的过程性记录反而很难找到。我自己当年也是从跑通一个模型开始一步步踩进数据管线、实验管理、服务部署、监控迭代这些深水区回头再看这个从会训练到会工程的过程才是AI工程真正的核心。这篇文章就打算把我从零搭建AI工程的完整思路、做的关键选型、踩过的坑和沉淀下来的方法系统性地梳理一遍。标题里的from scratch并不只意味着从空项目开始更意味着从只关注模型的思维里走出来去建立一套能撑起真实业务场景的工程体系。不管你是刚入行的算法工程师还是准备把AI能力落地到产品里的后端开发只要你正在面对模型跑通了然后呢这个问题这篇文章应该都能给你一份能直接抄作业的路线图。我会尽量把为什么这么做也解释清楚而不只是给你一堆命令和配置。因为AI工程里真正难的不是某个工具不会用而是当你面对十几个选项时不知道该凭什么做取舍。这些取舍背后的逻辑才是从零开始最大的价值。1. 重新认识AI工程它不只是跑模型先说一个我自己的观察。很多刚开始接触AI的人对AI工程的理解其实就是把模型训练出来精度还不错。这个理解本身没错但它只是整条链路里很小的一段。真实生产环境中的AI工程更像是一条流水线数据从哪里来怎么清洗和验证特征怎么算模型怎么训练和评估模型怎么提供服务线上的效果怎么监控出问题了怎么回滚新数据来了怎么增量更新。任何一个环节断掉整个系统都跑不起来。1.1 训练模型之外工程化才是真正的分水岭我见过不少团队模型在离线评估集上刷到了很漂亮的数字但一上线就崩线上请求的特征分布跟训练数据差得十万八千里推理延迟高到无法接受训练好的模型文件一换环境就加载失败甚至因为一个小小的数据预处理逻辑在前端、后端、离线脚本里各写了一遍三份逻辑对不上模型输入直接被污染。这些问题没有一个是在训练模型这个环节暴露的但它们才是决定一个AI项目能不能活下去的关键。所以AI工程的分水岭其实是从模型跑通之后才真正开始的。你要考虑的问题会从一个怎么提高两个点变成一大堆更务实的怎么保证、怎么监控、怎么迭代。举个生活化的例子会做饭跟开餐厅完全是两码事。前者只需要把菜做得好吃后者得操心食材供应链、出餐速度、口味一致性、卫生标准和顾客投诉处理。AI工程就是把会做饭的能力升级成开餐厅的体系。1.2 从零开始的路径依赖与心智模型从零开始这个词很容易让人陷入一个误区以为要把所有东西都自己造一遍。我自己刚开始也有这样的倾向什么都想自己写最后维护成本巨大。后来才明白从零开始真正需要的不是重新发明轮子而是建立正确的心智模型知道每一层可以借助什么现成工具自己应该集中精力做哪一部分增值最多的事。我比较推荐的心智模型是这样的把整个AI工程拆成三层。最下面是基础设施层包括GPU资源、存储、训练平台、CI/CD这一层尽量用成熟方案别自己折腾。中间是流程层包括数据管线、实验管理、模型服务、监控告警这一层要用好工具但要理解原理也好几天都说不完apikey之类的事。最上面是业务层包括问题定义、特征取舍、评估指标设计、线上策略这一层才是你的核心竞争力和价值所在。阿里、字节这种大厂自己搭建平台没问题但对大多数团队来说把精力投入到业务层用被验证过的工具去支撑基础设施层和流程层性价比要高得多。2. 从零起步搭建AI工程的核心技术底座技术底座这个事看起来最八股实际却最影响后面所有的体验。我见过有人进公司第一天就发现环境装不上环境变量配了三天最后发现是Python版本不对。也见过有人因为没做依赖锁定半年后又想重新跑当初的实验结果模型就是复现不出来。这些事都不难但不提前做后面就是持续的地狱难度。2.1 语言与框架选型Python不是唯一答案说到语言和框架Python肯定逃不掉AI的生态大部分都在Python这边这一点短期内不会改变。不过我需要专门提一句Python是主力但不是全部。你的工程里总有些性能敏感的环节比如大规模前处理、实时推理、并发服务这个时候用Go、Rust或者C写一部分高性能模块再通过Python做胶水层是很常见的架构。框架选型上PyTorch目前是最符合直觉的一个动态图机制让调试变得非常舒服大多数开源模型也都以它为主要支持。TensorFlow在生产部署上仍然有优势它的SavedModel和TFLite生态比PyTorch的TorchScript、ONNX方案要成熟不少。我的个人建议是如果你没有历史包袱也没有特别明确的部署约束直接选PyTorch起步。之后通过ONNX导出作为中间表示已经可以覆盖绝大多数的跨平台部署场景。2.2 环境管理与可复现性第一步就要做对环境管理是那种你不花十分钟做后面就得花十小时补的事情。我刚从零搭建第一个AI工程时图省事直接在一个基础环境里pip install了一堆包。过了两个月另一个项目需要旧版本依赖一冲突就是半天。后来我换了conda加virtualenv并用的方式每个项目一个独立环境并且额外做了依赖锁定问题才真正收敛。具体操作上我用的是conda管理Python版本和系统级依赖virtualenv管项目级的包隔离。我的conda base环境几乎是空的每个项目单独建一个简单环境比如conda create -n ai_eng python3.11。然后项目根目录下固定放requirements.in和requirements.txt两个文件前者记录直接依赖的包名尽量定版本范围后者通过pip freeze锁定全量精确版本。这样既能让人看懂你直接用了哪些包也能保证clone下来之后一行命令就能复现环境。复现实验的时候把这个requirements.txt和代码一起提交基本上不会再遇到怎么你那边能跑我这边就挂了的问题。2.3 算力规划与成本意识决定你能走多远算力是整个AI工程里最容易失控的成本项。我见过有人训练一个小模型起步就开了8卡分布式结果半天调不通通信时间全浪费在debug上。我也见过有人用单卡训练大模型跑了两天发现OOM了还硬撑最后checkpoint都没存下来。算力规划的第一原则是能单卡解决的问题坚决不分布式能用混合精度解决的问题坚决不全精度跑。大多数业务场景下的模型单张消费级显卡或一块云上的入门级GPU就够用了分布式训练带来的收益远没有你想象的那么大但复杂度却是实打实的。如果确实需要比单卡更大的算力也不急着直接上分布式。先考虑用梯度累积做小批次训练再考虑显存优化技术最后才是多卡。多卡场景下也要先想清楚是Data Parallel还是ZeRO阶段式的参数并行不同方案对带宽的要求差别很大。算力规划还有个容易被忽略的点把一次性训练和持续重训分开规划。一次性训练可以用抢占式实例便宜但可能会被回收持续服务必须用稳定的按量实例避免训练一半断掉。这两类需求混在一起规划成本核算和稳定性都会出问题。3. 数据与特征工程80%的时间花在这里如果你在AI行业待过一段时间一定听过一句话数据和特征决定了模型效果的上限算法只是去逼近这个上限。这句话我越来越有体会。做AI工程半年后再回头看模型和算法在整个项目时间占比其实不高真正吃掉时间和精力的是数据处理、验证和特征层面的功夫。这一节想把我在这个环节踩过的坑和沉淀的方法都说清楚。3.1 数据管线的设计原则数据管线说白了就是回答一个问题原始数据是怎么一步步变成模型输入的。我见过不少项目数据处理的代码散落在各种notebook和脚本里一段在训练时跑一段在预处理时跑还有一段在线上的推理服务里以另一种方式实现。结果就是同一批数据在离线、在线两套逻辑下产出的特征分布不一致模型上线后效果打折扣甚至崩掉。这种问题一旦出现排查起来极其痛苦而且很难通过调模型解决。所以我的数据管线设计原则非常明确一套代码双端复用。核心特征是同一个处理函数离线训练和在线推理都用它来算。实现上可以把数据处理封装成独立模块用配置文件区分运行环境通过一张映射表来保证离线、在线两套代码做的是完全一致的转换。为了实现这一点可以通过组件化的方式把各个处理步骤拆成可配置的算子加上参数校验快速定位不一致。这条原则看着简单做起来需要克制住先上线再说的冲动但它能帮你避免掉大部分线上线下不一致的经典问题。3.2 数据质量验证与版本化数据质量验证在AI工程里经常被当成额外的工作而不是必要的工作。我踩过一次大跟头某段时间模型效果持续下滑最开始以为是数据漂移排查了半天发现是上游任务改了字段定义某个ID字段从数字变成了带前缀的字符串结果训练数据里混入了一大批异常样本。这个事打了个措手不及。那次之后我就把数据质量验证提上了日程至少要有三层校验schema校验字段类型、缺失率、值域范围、业务规则校验比如金额不能为负ID必须唯一、统计校验对比当前一批数据和历史数据的关键分布指标比如均值、分位数、类别占比。数据版本化同样是很多团队会忽略的事。模型效果要可复现除了代码和参数要锁版本训练数据也得锁版本。我的做法是一个简单的版本目录每次数据管线跑完把产出的文件放到以时间戳和hash命名的目录里同时在训练配置里记录这个数据版本。这样出了任何问题都能快速定位是代码变了、参数变了还是数据变了。数据版本化不需要引入太重的大数据基础设施一个命名规范加一个hash记录表就能在早期撑住绝大多数项目的需要。3.3 特征工程与数据泄漏的坑特征工程环节最容易出两种问题一种是把所有信息一股脑喂进去根本不管特征的时效性和因果方向另一种是特征之间高度相关导致模型解释性和稳定性都很差。新手做特征工程最常见的问题是未来泄漏就是不知不觉中用了未来才能知道的信息。举个例子你在做流失预测却把用户后续一个月的操作频次作为特征放进了训练集。离线验证时效果高得离谱线上完全失效。这种坑一旦踩进去最难的地方在于你很难发现问题出在这里。我的做法是给每个特征打一个时间戳属性计算它在预测时刻是否可知。不可知的特征坚决不要或者设计成滞后统计量。除了泄漏问题特征保鲜度也要注意有的特征只在特定时间段内有意义比如大促期间的购买行为特征如果拿它去预测平时的转化准确率会受到很大影响。所以还要给特征本身加一个保质期概念定期评估特征的有效性及时下线失效特征。4. 模型开发与训练实操从基线到迭代模型训练这块很多文章都在讲怎么设计网络、怎么调网上的公开技巧。我想换个角度用工程化的视角来审视这一段的整个流程。毕竟对AI工程来说模型本身只是流水线上的一个环节如何组织实验、如何评估、如何迭代这些工程化的方法往往起到了决定性作用。4.1 基线模型先跑通再谈优化我自己有一个很固执的习惯任何项目中第一次跑模型永远不追求性能上限而是追求全链路跑通。这个基线模型的效果可能很普通但它必须把从数据读取、特征计算、模型训练到评估输出的整个链路完整串起来。在第一次全链路跑通之前谈任何优化都是空中楼阁。道理很简单只有在一条完整可运行的链路上你才能知道瓶颈到底在哪里。有些人一上来就上最复杂的Transformer特性然后从早调到晚却连简单的逻辑回归都还没跑通。这种本末倒置的做法往往会导致项目推进非常慢。行业里管这种做法叫建立基线。基线模型通常选择数据流最简单的模型结构逻辑回归、简单的树模型或者一个小型embedding模型都可以。基线模型还有一个重要的作用是提供对比基准后续所有优化动作都要跟这个基线对比好知道每一步改进到底是真有用还是只是你自我感觉良好。没有基线的优化就是一场没有记分牌的比赛。4.2 训练实验管理的三件套训练做多了之后你会发现实验管理比训练代码更重要。没有实验管理的时候你可能是靠model_v2_final_0822(居然还真的有最终版三连)来追踪模型。这样的命名方式轻则保留着几十个相互纠缠的文件夹重则出现我调了一个好的效果但复现不出来的惨案。我的经验是实验管理至少要做好三件事训练参数(hyperparameters)记录、训练日志(metrics)记录、模型文件(checkpoint)管理。先说训练参数的记录。每一次训练开始前我会把batch size、学习率、优化器参数、数据版本、模型结构定义等全部写入一个配置。最简单的做法是把这些参数原样保存成一份JSON或YAML跟模型文件放一起。复杂一点的做法是用实验管理工具如MLflow、WB来做集中管理。不过要提醒一句工具不是重点重点是你每次实验的config必须被完整记录而且模型文件本身要能和config一一对应。否则你几天后看着一个检查点会完全想不起它的训练参数是什么。再说训练日志。一边训练一边把训练集和验证集的loss、accuracy等指标记录下来最好还能画出曲线。这不仅仅是用来观察收敛情况的更重要的是它能暴露很多异常信号loss不下降、验证集指标抖动剧烈、训练和验证指标差距越来越大这些都能帮助你尽早发现超参数问题或者开始过拟合。这里有一个我自己的心得日志记录的频率不要太低至少每个epoch记录一次甚至可以考虑在每一步训练时都记录指标因为有些问题比如偶发的loss尖刺在epoch级的日志里会被平滑掉难以察觉。最后是模型文件管理。每次训练结束不要只保存最后一轮的checkpoint要至少保存效果最好的按验证集指标和一两个关键epoch的中间checkpoint。checkpoint保存要包括模型权重、优化器状态和epoch编号。训练中断时要能从最近的checkpoint续上训练而不是从头再来。这三件事做到位了实验管理的基本盘就算打牢了。再往前走才谈得上自动化调参、多实验并行这些进阶操作。4.3 模型评估不要盲目相信排行榜数字模型评估是连接训练和上线的质检环节。可很多把AI工程概念挂在嘴边的人对评估的理解还停留在跑了一遍测试集看到准确率完事的程度。这样做的风险在于你看到的指标可能并不能代表真实业务效果。比如分类任务里类别极不均衡你的模型把所有样本都判成多数类准确率照样有95%但这个模型对业务一文不值。又比如你做召回任务只看了离线Recall10却没看线上真实用户点击反馈结果离线效果再好线上业务照样没增长。我做的评估方案一般拆成三个层次。第一个层次是基础指标包括准确率、召回率、F1、AUC这类按任务类型选择的通用指标它们是体检报告里最基础的数据只能做初步体检不能只看它们做完全判断。第二个层次是分层评估把预测结果按不同用户群体或者不同业务类型拆开看。例如在一个用户推荐系统里新老用户的效果可能会差很多你是混合在一起评估一定会掩盖掉新用户召回效果差的问题。第三个层次是模拟线上行为评估比如用回放的方式用线上的日志数据来模拟模型的推理效果或者做小流量AB测试。只有做到这三层模型评估才算真正闭环。5. 部署、监控与持续迭代真正接近工程模型训好了、评估也过关了接下来就是上线。这一步是AI工程四个字里工程含量最高的一段。很多在实验室里没考虑过的问题都会在上线瞬间集中爆发模型文件太大加载太慢、并发请求压垮容器、延迟让调用方无法接受、训练数据分布和线上实时分布有偏差。下面是我在这条路上逐步积累起来的实践框架。5.1 模型服务化在线推理与批处理架构取舍模型服务化第一步是搞清楚你的使用场景是用户在页面上点了一下要求毫秒级返回结果还是每天凌晨批量处理几百万条历史数据这两种场景的架构选型完全不同。在线推理要求低延迟、高并发一般会用专门的推理服务通过REST或gRPC接口对外提供能力。为了降延迟需要把模型加载进显存/内存常驻用Batching的方式合并并发请求一次性通过GPU计算。批处理场景则更看重吞吐量可以用离线任务的方式调度大量任务并行处理跑完把结果写回存储即可延迟要求宽松成本反而更要敏感。在线推理服务里有几个容易忽略的细节。第一个是预热。模型加载到服务里之后不要立刻开始接正式流量先用一些测试请求跑几遍热身让缓存、显存分配、算子编译都达到稳定状态。否则前面几个请求的延迟会异常高。第二个是并发Batching策略。不要一个请求就占一次GPU计算把多个请求凑成一个batch会明显提升吞吐但也需要注意最大延迟约束等多久都凑不齐一个大batch时就该及时出发不要为了吞吐牺牲SLA。第三个是模型版本管理。线上服务可能有新旧模型同时提供服务的阶段接口层需要支持按版本路由。我用过的最简单方案是给模型加一个version参数请求方显式指定走哪套模型灰度阶段很方便。5.2 监控体系的三层结构监控是AI工程里最容易偷懒、又最容易翻车的一环。我早期没做监控的时候模型出问题总是被业务方投诉之后才发现非常被动。后来我按三层结构做监控情况才彻底好转。第一层是服务健康监控。这是最基础的包括请求量、错误率、延迟P50/P95/P99、GPU显存占用、CPU负载。这一层监控的意义在于任何服务级别的故障服务挂了、接口报错、物理资源异常都能第一时间暴露。具体的告警阈值需要根据实际服务能力定比如P99延迟超过500ms就告警。第二层是数据漂移监控。这是AI系统特有的。模型预测服务的线上真实输入特征分布跟模型训练时的特征分布会随着时间推移慢慢发生变化。比如用户的年龄结构变了、某个特征的取值范围漂了、或者上游数据源改了统计口径。数据漂移通常不会让服务立刻挂掉但会让模型的精度缓慢下滑属于慢病。数据漂移监控的常见做法是定期从线上采样真实推理请求对比它们的特征分布与训练集特征分布的差异常用的指标有PSI(Population Stability Index)或者KS统计量。一旦偏差超过阈值就触发告警提示可能需要重新训练或者回滚。第三层是业务效果监控。这是最接近业务价值的一层。模型上线后它对实际业务指标有没有起到正向作用比如转化率提升了没有、点击率变化了多少、客服转接率有没有下降。这一层的监控往往需要跟业务系统打通从最终的业务结果里反馈回来而不是只看模型自己的输出。业务效果监控发现的问题往往是最值得重视的信号——它说明模型策略层面的假设出了问题而不仅仅是工程执行层面的故障。5.3 迭代闭环如何让模型持续变好模型上线只是一切的开始这句话真的不是套话。一个模型投产后线上数据会源源不断地产生新样本环境也在不断变化。要让模型持续保持好效果就必须建立一个监控-反馈-重训-部署的迭代闭环。这里有几个关键决策点值得展开讲一下。第一个决策点是什么时候触发重训。我不建议拍脑袋定每周五固定重训更好的方式是基于监控告警和数据新鲜度来定。当数据漂移监控发现特征分布出现显著变化或者业务效果指标连续多日下滑就要触发重训。当然也可以做一个定期兜底比如每个月至少重训一次防止一些缓慢变化被忽略。第二个决策点是重训样本怎么选。天然的方式是尽量拿最新的数据让模型去适配当前的环境。但也要注意保留一部分历史关键样本防止灾难性遗忘——比如某个旧但重要的模式在新数据里已经很少出现模型很容易把它忘掉导致旧场景效果突然变差。所以我的样本选择策略一般是一个带时间权重的滑动窗口最近三个月的数据为主加上一小部分历史关键样本做回放。第三个决策点是自动重训的成熟度。初期团队的自动重训可以做成半自动系统提醒应该重训了人工确认并跑一条训练任务然后人工审核评估结果后再部署。等评估体系和监控体系都足够可靠了再逐步走向全自动。一上来就全自动重训一旦数据标签有异常就会训练出个错误模型直接上线危害非常大。自动化的每一步都要确认已经有对应的质量闸门。6. 常见问题与排查技巧实录这一节是我最想写的部分。很多知识你在文档里都能查到但真实项目里会遇到什么问题这种事只有踩过坑的人才能说清楚。我把这些年做AI工程从零搭建过程中反复遇到的典型问题挑几个代表性的整理在这里按排查思路来展开。6.1 新手最容易犯的五个错误我已经在前面各节中零散提到了不少这里集中盘一盘方便你对照自查。第一跳过基线一上来就追SOTA。好多人第一次训模型就想用最复杂的结构看到loss降得比baseline快就觉得自己很行。结果是模型结构复杂到无法快速迭代一个超参数调半天整个项目的时间全都耗在那儿。我的建议永远是先把最简版本跑通再层层加码。第二线上线下处理逻辑不一致。这是我反复强调的问题。离线训练时你做了一堆数据清洗和特征工程到了线上推理服务你图省事又手写了一份逻辑。两边对不齐模型效果就会受损而且你很难定位到具体原因。从第一天开始把数据处理封装成共享模块是唯一稳妥的解法。第三不锁版本包括代码、环境、数据。我见过太多复现不出实验结果的惨案最后发现不是代码问题是某个依赖包偷偷升级了或者是训练数据文件被覆盖了。版本锁定这件事一定要从第一天开始养成习惯。具体可参见我前面讲的环境管理和数据版本化。第四评估指标单一且脱离业务。只看准确率不看分层表现不模拟线上行为。结果是模型榜单好看业务不涨。做评估至少要做到前文说的三个层次尤其不能漏掉分层评估和线上行为模拟。第五忽略监控和告警。模型上线就撒手不管等出问题被业务方投诉才知道。监控的三层结构看起来麻烦但没做监控的系统本质上是不受控的。务必要把服务健康、数据漂移、业务效果这三层监控都补上哪怕先用最简单的日志加定时脚本。多花点时间在监控上后面会让你比以前幸福得多。6.2 典型问题的排查思路实录这里挑两个我也真实处理过的问题把排查过程写出来比直接贴一段告警配置更有价值。第一个问题是线上推理延迟突然从50ms飙升到500ms。我遇到之后第一时间先看监控面板确认是不是请求量暴涨导致的资源瓶颈。结果请求量没变化GPU利用率反而只有不到30%。这就说明不是算力不够而是可能有慢请求卡住了。我接着往下查发现是数据预处理环节里有一段正则表达式在某个特定文本上触发了灾难性回溯导致单个请求处理时间极长。这是因为那段处理逻辑在离线时数据分布没有覆盖到这种极端case线上才暴露。排查到根因之后把正则写法改掉延迟就恢复了。这类问题如果第一反应是膨胀资源那就走弯路了。排查的顺序要反过来先确认不是代码逻辑问题再考虑加资源。第二个问题是模型上线一周业务指标不升反降。从监控上看服务健康正常数据漂移也没有告警但转化率就是降了。后来排查发现问题出在样本标注策略上我们用的是用户发生转化后7天内的行为做正样本但线上模型上线后系统开始根据模型的推荐调整排序导致用户行为分布改变了进而影响了新样本的标注质量形成了一个负反馈循环。这个案例的启发是模型上线后业务本身也会因为模型的存在而改变训练和评估的假设可能需要重新审视。这也是为什么业务效果监控和迭代闭环必须闭环起来不能只靠一次上线一劳永逸。6.3 个人总结:一把衡量AI工程成熟的尺子在多年的实践里我慢慢形成了一个简单的判断标准用来衡量一个AI项目到底算不算工程化了。我会问五个问题第一如果换一台新机器你能在一天之内把环境和数据完全复现出来吗第二如果线上模型效果突变你能在多长时间内定位是数据、代码、模型还是环境的原因第三模型训练和线上推理的特征逻辑是不是同一套代码第四除了模型本身的指标你有没有在监控业务结果指标第五模型多久能被重新训练一次迭代一次的成本是多少如果这几个问题的答案都是令人满意的那你的AI工程就可以说是真正立住了。如果答案还很模糊别灰心对照上面每一节的内容一处处补你会看到阶段性进展。我始终觉得AI工程这件事没什么玄学它就是大量的标准化动作加上对为什么这么做的坚持。从零开始也没有多难只要愿意在前期多做一些看起来慢、但后来会无比省心的事情就行。最后再分享一个我个人的小习惯。每做完一次训练任务我都会把当时实验的配置、关键日志的截图、遇到的问题和解决方式单独记在一个维护的笔记文件里连同模型文件一起归档。哪怕项目过去半年一年回头翻这个笔记当时踩了哪些坑、为什么改成现在这个方案全都一目了然。这个习惯帮我免去了无数当时的我到底是怎么想的的困惑。做AI工程踏实的记录比聪明才智更可靠。
返回列表