很多人一提“AI 工程”,第一反应就是“训练模型”。我在一线做了十几年算法和工程,见过太多团队把绝大部分精力砸在调模型上,最后却死在了数据、评估、部署这些不起眼的环节上。ai-engineering-from-scratch这个题目,想表达的正是这件事:从零开始把 AI 真正落地,不是跑通一个 Notebook,而是跑通一整条包含问题定义、数据链路、模型迭代、上线监控的工程链路。这篇文章我会按自己实际带项目走的顺序,把每个阶段最关键的决策、最容易踩的坑、以及可以照着抄的步骤都写清楚,适合刚组建 AI 团队的负责人、独立开发者,以及想从算法岗转向工程岗的朋友。
1. 先想明白:AI 工程不是堆模型,是把问题翻译成可计算的东西
很多项目死在第一步,不是因为技术不行,而是因为问题压根没定义清楚。业务方说“我想预测用户流失”,这句话听起来清楚,但落到工程上全是问号:用什么数据定义“流失”?预测的时间窗口是多久?预测出来之后运营动作是什么?这些问题不解决,后面做再多都是白做。
1.1 从业务问题到机器学习问题的翻译
我习惯用一个“三问法”来开场,跟业务方对齐时反复确认这三个问题:
- 决策点是什么:模型预测结果出来后,谁会做什么动作?比如“用户可能流失”这个信号,对应的动作是发优惠券、安排客服回访,还是什么都不做。
- 输入输出边界:预测发生在什么时间点?能拿到哪些当时已知的数据?例如预测“未来 7 天是否会流失”,那输入就只能用截止到今天的数据,绝不能用未来数据,这是很多人容易犯的泄漏错误。
- 错误代价:漏掉一个真实流失用户和误判一个活跃用户,哪个代价更高?这直接影响后面模型阈值怎么调,离线评估看哪个指标。
这个过程产出的不是文档,而是一句话:“在 T 时刻,基于已知特征 X,预测未来 N 天内用户是否会发生事件 Y,预测结果用于触发动作 Z。”这句话会被写进项目 README 的第一行,是所有后续工作的锚点。
1.2 确定成功指标:离线指标与在线指标的统一
业务方爱问“准确率多少”,但准确率在绝大多数场景里都有欺骗性。拿流失预测来说,如果真实流失率只有 5%,那模型什么都不做、全部预测“不流失”,准确率也有 95%。所以我会把指标拆成两层:
- 离线指标:精确率、召回率、AUC 这些,用来快速比较模型版本,但它只是代理指标。
- 在线指标:真正衡量业务价值的指标,比如“挽回的用户数量”“活动成本 ROI”“留存提升幅度”。
这两层之间要有一条因果关系链:离线提升的召回率,预计能带来多少在线挽回用户。我见过最典型的翻车案例是:离线 AUC 涨了 0.03,所有人都很高兴,上线后业务指标纹丝不动。后来排查发现,新模型确实更准地识别出了“会流失”的用户,但运营团队根本没有足够的预算去触达所有高风险用户,瓶颈根本不在模型。所以从第一天起,就要把模型性能和业务动作的容量放在一起规划,离线指标只是手段,在线业务指标才是目的。
2. 数据是第一道坎:从原始日志到干净训练集的完整链路
模型训练只占项目周期的很小一部分,数据准备通常要占掉 60% 以上的时间。这不是夸张,是我带过的每个项目的真实比例。数据工作的核心不是“跑通”,而是“可依赖”——你要能说清楚每张表、每个字段、每个标签是怎么来的。
2.1 数据采集与探查:先搞清楚手里有什么
正式写训练代码之前,我会先花三到五天做数据探查,产出三样东西:字段字典、数据质量报告、采样样本集。
字段字典不用太复杂,至少包含字段名、含义、来源表、更新频率、是否可能有延迟。很多团队没有这份字典,两个月后自己写的特征都得靠猜,更别说新同事接手。
数据质量报告要重点看几件事:
- 缺失率:超过 70% 缺失的字段,除非业务上极其重要,否则直接放弃。
- 取值分布:分类特征的类别数、数值特征的最大最小和分位数。一个数值特征出现 -9999 或 99999,通常不是真实值,而是填充符。
- 时间跨度:数据覆盖了多久?有没有断档?时间断档对时序特征的影响比想象中大。
探查之后,我会随手写几个简单的分布图脚本,把关键特征的分布存成图片放在实验目录里。这些图在后面的错误分析阶段会反复用到。
2.2 标签体系的构建:没有标签一切算法都是空谈
标签决定模型的上限,特征和模型只是在逼近这个上限。所以标签定义一定要写进正式文档,并且经过业务方确认。
以“用户流失”为例,我通常会让业务方回答几个问题:流失是“连续 30 天未登录”还是“付费用户取消订阅”?统计窗口从哪天开始算?如果一个用户中间登录一次但没付费,算不算留存?这些细节不敲定,标注出来的标签就带着噪声,模型学到的自然也是错的。
实操上要注意标签的时间对齐。训练样本里每个用户每条样本,都要严格对应“特征截止时间”和“标签观察截止时间”。这个我建议画成时间轴图贴在团队墙上,虽然是纸笔功夫,但能避免大量低级错误。
2.3 数据清洗与版本管理:脏数据吃掉的时间远超模型训练
清洗这一步没有捷径,就是把脏数据一条条揪出来。常见的几类:
- 重复样本:用户行为日志被重复上报,导致同一用户同一时间段出现多条相同记录。
- 异常时间戳:日志里出现未来时间,或者时间戳明显错位。
- 单位不一致:有的接口返回秒,有的返回毫秒,合并时不做单位换算,特征数值直接乱掉。
这几类问题我用 Pandas 写脚本就能处理,但关键是把清洗逻辑固化成脚本,而不是在 Notebook 里手工改。清洗脚本和数据版本要绑定,每次清洗完生成一个新的数据版本号,类似dataset_v1.3。所有实验记录里必须写明用哪个数据版本,否则后续排查问题时,你根本不知道当时的模型学的是什么数据。
数据版本管理我推荐两种方案:小团队用 DVC 配合对象存储,大一点直接用 Iceberg 或 Delta Lake 这类表格式。核心不是工具,而是“数据不可变”的原则——已经发布的数据版本不允许原地修改,要改就生成新版本。这个习惯能救你无数次。
3. 模型选型与基线:别一开始就追 SOTA,先跑通一条最小闭环
选模型这件事,我见过两个极端:一种是什么热门用什么,LLM 火了就套 LLM,GNN 火了就试 GNN;另一种是永远用逻辑回归,怕新模型不稳定。我的建议是走中间路线:先建立一个最简基线,让整条工程链路先转起来,然后再有节奏地升级模型。
3.1 从最简单的基线开始
第一个基线模型通常不需要机器学习,可以是规则,也可以是统计方法。比如流失预测,我可以直接用“过去 30 天未登录次数 > 3 次即标记为高风险”这样的规则。别觉得规则丢人,规则模型的价值在于:
- 花一两天就能上线,让业务方看到完整的闭环流程。
- 给后续机器学习模型提供一个“必须超越”的及格线。
- 帮助验证数据链路是否正确,特征是否有区分度。
当规则模型跑通之后,再上逻辑回归或者树模型。像流失预测、风控、推荐排序这类结构化数据场景,XGBoost / LightGBM 通常在第一版就能取得不错的效果,不需要一开始就上深度学习。
3.2 模型复杂度与训练成本的平衡
我在选型时会给每个候选模型列一张成本收益表,考虑的不只是离线准确率,还有三件事:
- 训练成本:单次训练要多久?V100/A100 的 GPU 成本是否承担得起?
- 推理成本:线上预测一次需要多少毫秒?并发上来之后单机能不能扛住?
- 维护成本:模型出问题时,团队里有没有人能看懂、能调?
很多时候,模型效果的差异远没有想象中大。我做过一个消费金融的评分卡项目,深度学习模型比梯度提升树只高了 0.5% 的 AUC,但推理延迟高了三倍,还多了依赖的 GPU 推理服务。最终我们选了树模型,省下的钱和人力全投入到特征迭代上,效果反而更好。
3.3 让模型跑起来的工程环境
这一节写给刚起步的团队。你不需要一开始就搭一套分布式训练集群,一台 8 核 32G 的云主机加上一块消费级 GPU(或直接用云上的训练实例)足够跑完第一版。但有几个工程习惯要从第一次训练就养成:
- 训练脚本要参数化:数据路径、特征列表、超参数都通过命令行或配置文件传入,禁止写死在代码里。
- 固定随机种子:确保实验可复现,否则你根本无法判断模型效果提升是来自新特征还是运气。
- 记录环境依赖:用 requirements.txt 或 conda 环境导出文件,避免三个月后依赖冲突跑不起来。
我甚至建议用脚本一键提交训练,而不是手动在 Notebook 里点运行。因为手动操作无法追溯,也无法让其他人接手。好的工程环境不是多豪华,而是“别人也能一键跑通”。
4. 评估与调优:用错误分析代替盲目调参
模型跑出第一个版本后,最忌讳的事情就是立刻开始调参。我在复盘时发现,很多项目的效果瓶颈根本不在超参数,而在特征质量、标签噪声和数据泄漏上。与其浪费算力去搜参,不如先做一次系统的错误分析。
4.1 划分数据集时要小心的时间泄漏
时序数据的切分和随机切分完全不同。流失预测、销量预测、推荐这类场景,如果随机打乱数据来划分训练集和测试集,训练集里的“未来”信息会泄漏给模型,测试指标会虚高得离谱。
正确的做法是按时间切分:用前 80% 时间窗口的数据做训练,中间 10% 做验证,最后 10% 做测试。验证集和测试集必须在时间上严格晚于训练集。这条规则我强调无数遍,但每次新人加入团队还是会犯。尤其要小心特征构造时的“未来函数”——比如用第 T 天之后的数据去构造第 T 天的特征,这在离线评估时几乎无法察觉,上线后效果却会明显缩水。
4.2 错误分析:把测试集上的坏案例逐个看一遍
拿到第一个版本的测试结果后,我会做这样一件事:把测试集里预测错的样本全部捞出来,按错误类型分成几组,然后每组随机挑几十条,去看它们到底长什么样。
具体做法是写一个分析脚本,输出每个错误样本的特征快照和真实标签。比如用户流失预测,我会看:被漏掉的用户里,是不是都集中在“低收入高活跃”群体?被误报的用户里,是不是都被最近一次大促干扰了行为?看到足够多的样本后,错误的模式会自己浮出来。
我经历过的错误分析结论举几个例子:
- 某个特征在不同平台上定义不一致,导致跨平台样本表现差异巨大。
- 标签定义有歧义,标注人员长期把“一周内回访”的用户标成了流失。
- 某个渠道的用户行为数据漏采了一个月,模型的预测对这部分用户完全失效。
这些问题没有一个是靠调参能解决的。特征层面的修复往往让模型的提升远比 grid search 来得快。
4.3 超参数调优的边界
错误分析之后,如果模型基线仍然偏低,再考虑超参数调优。我的调参策略是“先粗后细”:先固定几个明显重要的参数,做一次大范围的随机搜索,选出几个候选区域;再在候选区域里做细粒度搜索。
这里想提醒一句:不要盲目追求贝叶斯优化、遗传算法这些花哨的调参工具。对于中小型数据集,随机搜索配合少量人工判断通常就足够了。调参的目标不是找到理论最优解,而是找到“性价比最高的解”。我把超参数调优的过程记录下来,每次实验都记录参数组合和结果,形成自己的经验库,下次再遇类似问题可以直接参考。
5. 部署与监控:模型上线只是开始,漂移才是长期对手
模型训练完成不等于项目结束。很多 AI 工程从“能跑”到“能稳定跑”,差距就在部署和监控这两个环节。模型上线那一刻,才是真正考验工程能力的开始。
5.1 部署形态选择:离线批量、在线同步还是流式
不要因为“在线实时”听起来高级就选它。部署形态应该由业务需求决定:
- 离线批量预测:适合对时效性要求不高的场景,比如每日用户分群、批量风险评估。实现最简单,凌晨跑定时任务,结果写回数据库。我们第一版流失预测就走这个方案,每天凌晨更新预测结果,白天的运营按结果执行触达,完全够用。
- 在线同步预测:适合需要毫秒级响应的场景,比如实时推荐、实时风控。需要把模型封装成 HTTP 或 gRPC 服务,还要考虑超时和降级。
- 流式预测:适合事件驱动且需要秒级响应的场景,比如实时反欺诈,要求数据管道和模型服务都具备流式处理能力,工程复杂度最高,通常放在业务稳定后二期再上。
我的建议是:MVP 阶段能用离线批量就用离线批量,它能更快验证业务价值,后期再逐步迁移到在线服务。
5.2 模型服务化:性能、容灾与灰度
如果确实需要在线服务,有几个实践细节值得写下来。
模型文件管理要规范和代码一样对待,用模型仓库管理,每次发布记录版本号、训练数据版本、指标表现。服务上线采用蓝绿部署或灰度发布,先切 5% 流量观察几分钟,确认在线指标没有异常再放量。
性能方面,我会关注三个指标:
- P99 延迟:不是平均延迟,而是最慢的那 1% 请求的耗时。平均延迟好看不代表线上体验好。
- 吞吐量:单实例每秒能处理多少请求。用压测工具在发布前测清楚,别等线上被打爆了才临时扩容。
- 内存占用:树模型一般很小,但深度模型可能上百 MB,加载到内存的时间和推理耗时都要压测。
容灾设计也不复杂,但必须有:模型服务挂了之后,接口要能快速降级到规则方案或返回兜底值。记住,Model serving 的可靠性要求不低于业务后端,因为它已经是核心业务链路的一部分了。
5.3 监控体系:预测分布、特征漂移与反馈闭环
模型上线后,我至少要盯三类监控:
- 系统监控:请求量、延迟、错误率、资源占用。
- 数据监控:输入特征的空值率、取值分布、特征漂移程度。比如我们曾经发现某个上游数据源的字段单位从“天”变成了“小时”,特征分布一夜之间全变了,模型预测结果也跟着乱掉。
- 业务效果监控:预测结果带来的业务指标变化。这部分最难,因为需要设计因果对比方案,比如随机留一部分用户不做干预,来估算模型带来的增量效果。
漂移检测不用搞得太复杂,最简单的做法是每天对比当前特征分布和训练集分布的 PSI(群体稳定性指数)。PSI 超过 0.2 就报警,运营和算法一起排查原因。我曾经靠这个监控,提前一周发现了一个上游业务策略调整对模型带来的系统性冲击,赶在业务投诉前做了模型更新。
6. 团队协作与工程规范:从一个人能跑到一个组能稳定跑
个人项目可以靠脑子记,但团队项目必须靠规范。一项 AI 工程如果换了个人就没人能接手,那它还不算真正完成。
6.1 实验追踪:没有记录等于没做
跑实验的时候,大家普遍有侥幸心理:“这个改动很简单,不用记录。”但一个月后回头看,几十个实验全都长一个样——你已经分不清哪个是最好的模型,用的是什么数据、什么特征、什么参数。
从第一天起就要用实验追踪工具,比如 MLflow、Weights & Biases,或者最简单的 CSV 记录表。每条实验记录至少包含:
- 实验名称和目标
- 数据版本号和特征清单
- 模型类型和超参数
- 离线评估指标
- 错误分析的结论链接
- 代码版本号或 commit hash
这套记录习惯带来的最大收益是,你能随时回溯“为什么这个模型效果好”的完整上下文,而不是靠模糊记忆。
6.2 代码、模型与数据的版本协同
AI 工程和传统软件开发最大的不同在于,产物不只是代码,还包括数据和模型。三者必须能一一对应。我推荐的做法是:
- 代码用 Git 管理,每次训练前打 tag。
- 数据用 DVC 或专门的存储目录管理,目录名带版本号。
- 模型用模型仓库管理,训练产出的模型文件绑定对应的数据版本和代码版本。
配合上模型注册表,每个候选模型上线前都要有完整的“溯源链”,包括谁训练的、用的什么数据、评估结果如何、谁批准的。这个机制在审计和排障时价值巨大。有一次线上模型效果大跌,我们靠这个链路快速定位到是上游特征口径变化,而不是模型本身出了问题。
6.3 可复现性:让三个月后的自己还能跑通今天的实验
“可复现”不只是科学严谨性的要求,更是工程效率的要求。我给自己定过一个规矩:任何一个实验,如果换一台干净机器按文档操作不能完全复现,这个实验就等于没做完。
为了让每个实验可复现,我做了这几件事:
- 把训练入口统一成一个脚本
train.py,所有参数通过 YAML 配置文件传入。 - 把依赖包版本用 lock 文件固定,不只是列出顶层依赖。
- 每次实验记录容器镜像 ID,避免宿主机环境漂移影响结果。
- 在实验目录里写一个
README.md,记录运行命令和数据来源。
这套做法前期会多花一些时间,但长期来看,省下的返工时间至少是十倍。
7. 从零到一的整体路线图与时间分配
最后给一张可以直接参考的路线图,用于规划一个 3 个月从零到上线的 AI 工程落地项目。这个节奏是基于我往年带项目的经验,数据基础一般的团队也可以照着调整。
7.1 一个可抄的 12 周路线图
第 1-2 周:问题与数据盘点
- 完成业务问题到 ML 问题的翻译。
- 确定成功指标和基线规则模型。
- 梳理所有可用数据源,产出字段字典和数据质量报告。
第 3-4 周:标签与特征工程
- 和业务方敲定标签定义,完成标注或自动打标脚本。
- 构建第一批特征,写清楚特征加工逻辑,产出特征版本。
- 完成数据清洗脚本,形成 V1.0 数据集。
第 5-6 周:基线模型与评估闭环
- 跑通规则基线和第一个机器学习模型。
- 建立训练验证测试的划分标准,尤其是时间切分逻辑。
- 完成第一次错误分析,形成问题清单。
第 7-8 周:迭代优化
- 根据错误分析修复特征、标签问题。
- 有节奏地做超参数调优。
- 记录所有实验,维护实验追踪文档。
第 9-10 周:部署方案
- 确定部署形态,先做离线批量预测最简单方案。
- 搭建监控体系,包括特征漂移和业务效果监控。
- 准备模型服务容灾与降级方案。
第 11-12 周:上线与复盘
- 灰度发布,小流量验证。
- 建立周度评估例会,持续监控。
- 复盘整个链条,补充工程规范和文档。
7.2 常见失败模式与我的建议
根据我带项目的经验,绝大多数失败可以归结为这几类:
- 数据挖掘不足就开工:拿到数据后不仔细探查,直接开始建模,最后发现特征全是垃圾。建议把数据探查当成里程碑,不完成不进入下一阶段。
- 指标错位:离线指标和在线业务指标脱节,模型在离线表现好但业务不涨。建议从第一天就把成功指标定义成在线指标,离线指标只做参考。
- 忽视监控:模型上线后不建立监控,等业务方反馈问题时已经造成大量损失。建议上线当天就部署监控,不要等。
- 实验无记录:团队快速迭代时退回到“手动记笔记”模式,导致实验混乱。建议用工具把记录变成流程的一部分,而不是额外负担。
我个人在实际执行中还保留一个习惯:每次项目复盘时,把所有踩过的坑整理成一份“避坑清单”放到团队知识库里。比如“时间切分必须强制”“字段单位合并前必须统一”“模型服务必须设置超时”。这些看似琐碎的条目,积累起来才是 AI 工程能力真正的沉淀。从零开始做 AI 工程,最大的门槛不是算法难度,而是你有没有把自己的工程习惯建立起来。先把第一条链路老老实实跑通,后面的事情会顺利很多。