做AI工程这件事,很多人都被“模型”两个字锁住了。看了几篇教程,跑通了一个resnet或者调用了一个大模型API,就觉得自己在搞AI工程了。实际上去企业里走一圈就会发现,真正值钱的、真正有瓶颈的,从来不是那行model.fit,而是模型之外的那条流水线怎么设计、数据怎么流动、效果怎么度量、模型怎么安全地上线。把标题里的“from scratch”拆开看,本质上是想表达一件事:完全不依赖现成的外部解决方案,从零开始,把一个AI系统当成一个严肃的工程系统来搭建。
这篇文章就是写给那些想绕过“调包侠”阶段,真正理解AI工程底层逻辑的人。无论你是打算转行做AI,还是已经在做算法但被工程化反复折磨,都可以把这里的内容当成一份路线图。我会从概念拆解开始,到环境搭建、数据管线、模型开发、评测部署,再到生产环境里的监控和迭代,全部串起来讲清楚。不回避难点,也不故作高深,把每一步背后的“为什么”说透。
1. AI工程到底是什么:从“写模型”到“做系统”
1.1 一个容易混淆的边界:AI工程、机器学习工程和数据工程
很多人把AI工程、机器学习工程和数据工程混成一个词,面试的时候也经常被绕进去。我的理解是:数据工程解决的是“数据能不能可靠地、高效地流动”,机器学习工程解决的是“模型能不能被稳定地训练、评估和部署”,而AI工程是更大的壳子,它把数据、模型、业务逻辑、反馈闭环全部捏成一个产品系统。
举个例子,你做一个商品推荐系统。数据工程师负责把用户点击日志从Kafka里捞出来,清洗好落到数据仓库;机器学习工程师负责训练一个召回和排序模型,把离线指标刷到某个阈值;AI工程师则是那个要对最终推荐效果负责的人,他得关心用户点了什么、模型推了什么、推荐结果怎么展示、用户反馈怎么回流、下一轮训练怎么利用这些反馈。这个闭环里任何一环断了,推荐效果都会下滑。
从零开始做AI工程,意味着你不能只盯着模型训练那一段,而是要把整个闭环都当成自己的地盘。很多人忽略这一点,最后模型做出来了,却跑不了一个完整的服务。
1.2 我从零开始搭建AI工程的里程碑
如果你问我,一个完全没有AI工程基础的人,应该按什么顺序进阶?我建议分四个阶段走。
第一阶段是建立系统视野。别急着上深度学习,先搞清楚一个AI系统由哪些模块组成:数据处理、特征工程、模型训练、离线评估、在线服务、监控反馈。你在纸上画一个数据流向图,把每个模块的输入输出标清楚,这一步能救你以后无数的命。
第二阶段是亲手实现一个极简闭环。不要用现成的ML平台,用Python手写一个数据读取函数、一个简单的训练脚本、一个基于Flask的模型接口,外加一个定时触发器。规模小到只有几百条数据也行,关键是让所有环节都真实跑通。
第三阶段是引入工程化工具。当手动环节太多,你觉得痛苦了,才开始引入版本控制、流水线编排、模型注册、监控告警。这个顺序很重要,先痛苦后工具,你才知道每个工具解决的是什么问题。
第四阶段是做质量保障和持续迭代。在这个阶段,离线评测、线上AB测试、数据漂移检测、模型回滚机制都要到位。能走到这里,你才算真正入了AI工程的门。
2. 从一个问题定义开始:选型与路线图
2.1 起点不是模型结构,而是业务问题的定义
从零开始做AI工程,最容易犯的错误就是一上来就问“用什么模型”。模型是手段,不是目的。真正应该先定义清楚的是:你要预测什么,预测结果给谁用,用错了的代价有多大。
这句话听起来像废话,但在实际项目里,我见过太多团队把问题定义错了。比如有个项目想做“异常检测”,业务方说只要模型能标出异常就行。结果深挖下去,发现他们的真实需求是“减少一线审核人员的工作量”,而且异常的定义会随着时间变化。如果不把“异常”这个标准用可量化的规则和人机协同机制定义清楚,模型做得再准也落不了地。
我每次启动一个新项目,都会强迫自己写一页纸的问题定义,包含五个部分:业务目标、预测目标、输入数据、输出形式、失败代价。写完之后还会拉上业务方逐条对齐。这个过程看起来很慢,但能帮后续所有技术决策找到依据。
2.2 技术栈选型:重框架还是轻框架
当问题定义清楚了,才轮到技术选型。现在的技术栈已经非常丰富,但我不建议直接用全家桶式的AI平台,原因是它会遮蔽掉工程底层的细节。从零开始的阶段,很多东西只有你自己动手做过,才能理解它的用途。
如果你做的是传统机器学习模型,比如梯度提升树或者线性模型,那首选就是LightGBM和XGBoost这一类库,它们训练快、可解释性好,在表格数据上依然是最强主力。我之前做风控模型的时候,80%的场景都用LightGBM搞定,简单有效。
如果是图像、文本等非结构化数据,PyTorch基本是事实标准。它的动态图机制让调试变得非常直观。TensorFlow也不是不行,但在工程生态上PyTorch更贴合研究到生产的过渡路径。你不想在部署时被奇怪的graph模式折腾的话,PyTorch会让你心理更健康。
特征存储、流水线编排、模型部署这些组件,我建议从最简单的开源工具开始。Feast可以作为特征存储入门,Airflow或Prefect处理编排,FastAPI或者MLflow做模型服务。这套组合虽然不像商业平台那么开箱即用,但每个组件的边界很清晰,出了问题你知道去哪个模块排查。
2.3 设定技术路线的关键决策点
除了框架选型,还有几个技术路线上的关键决策点,值得单独列出来。
GPU还是CPU,要不要分布式?如果你的数据量在GB级别,模型参数量在百万级别,一张消费级显卡就能覆盖绝大多数场景。不要过早引入分布式训练,多机多卡的复杂度会直接拖垮项目进度。我做过的很多项目里,单机单卡解决了90%的问题。
从头训练还是微调?如果领域数据足够且任务比较特殊,从头训练不是不行,但成本高昂。更稳妥的路线是:先用公开的预训练模型做baseline,再在你的垂直数据上做微调。这个策略能用最少的时间和精力,获得最接近理想效果的结果。
内部部署还是调用外部API?这取决于数据隐私和延迟要求。数据不能出内网,就必须自建模型服务;对延迟极其敏感,也要自建。其他情况可以考虑成熟的外部服务,把精力聚焦到业务闭环上。
3. 建设数据管线和实验框架
3.1 数据获取与版本控制:被低估的起点
数据是AI系统唯一的养料,这个说法一点都不夸张。从零开始做工程,最先要解决的不是训练,而是让数据稳定、可回溯地流进来。
我强烈建议从第一天就给数据做版本管理。你想象一下这个场景:周一训练模型用的数据集是V3版本,周二前处理脚本被同事改了一行,周三再训练出的模型指标变了,但你完全不知道是数据变了还是代码变了。没有数据版本管理,这个问题无解。DVC是我常用的工具,它能把数据集、标签文件、预处理脚本的依赖关系一起记录下来,每一次实验都能精确回放。
数据获取阶段还要注意一个隐蔽问题:数据分布和真实场景的偏差。训练数据往往来自历史积累,但真实场景里的分布是动态变化的。一个给电商做销量预测的项目,光用去年双十一的数据训练,今年再用效果就会明显变差。我的习惯是,在数据采集阶段就建立时间切片验证,用最近三个月的数据做验证集,检验模型在“未来”数据上的表现。
3.2 实验结果管理:从记事本到实验平台
很多初学者把实验管理等同于“在notebook里记几个acc数字”,这在你调试三五个模型的时候没问题,但一旦进入特征组合、超参数搜索、多模型对比的节奏,马上就会被淹没。
我建议用一个轻量级的实验跟踪工具,比如MLflow或者Weights & Biases。它们记录的内容非常明确:每次实验的代码版本、配置参数、训练指标、模型产物、环境依赖。你不需要记住“这版lr=0.01的acc是0.92”,工具会自动帮你按时间线组织好。
我自己常用的做法是:每个实验都固定一个全局随机种子,把数据切分方式、特征名称列表、模型超参数全部显式记录。评价指标不止记录最终的验证集结果,还会记录训练过程中的loss曲线。这样即使后续指标异常,也能从训练曲线定位是数据问题、收敛问题还是代码bug。
3.3 特征工程:让模型吃对食物
从零开始做特征工程,最大的陷阱是“贪多”。觉得特征越多模型就越强,然后一股脑堆了几百个特征,最后训练时间翻倍、模型解释性变差,线上特征和离线特征还容易对不上。
特征工程的核心原则是:先理解业务,再做特征。以用户流失预测为例,与其堆砌几十个用户属性,不如先想清楚流失行为的前兆是什么——登录频率降低、关键操作减少、客诉增加,这些由业务驱动的特征会比统计出来的相关特征稳健得多。
同时要保证离线特征和在线特征的一致性。这一点是工程里最常见的坑。离线训练时你用了未来信息,比如用当天的完整数据预测当天的流失,线上推理时根本取不到当天完整数据,模型效果自然就崩了。处理办法是建立一个面向特征的计算时间快照机制,训练和推理都只用历史某个时间点之前的信息。
3.4 从零搭建训练框架:几个关键设计选择
到了模型开发环节,有人会犹豫到底要不要直接用现成的训练框架。我建议把“训练脚本”和“训练框架”分开来看:模型结构可以直接用开源实现,但训练流程最好自己组装一遍,这样才能理解每一步的逻辑。
一个标准训练循环包含数据加载、模型前向传播、损失计算、反向传播、参数更新、指标记录这几个环节。PyTorch里面的写法很固定,但你如果不亲手写一遍循环,理解不了batch size对梯度稳定性的影响、学习率调度对收敛速度的作用,更不懂为什么需要梯度裁剪。
我自己习惯把训练流程拆成三块:数据集类负责取数和预处理,模型类负责前向计算,训练器负责梯度更新和评估。边界清晰之后,换模型、换数据、换损失函数都变成插件式操作,测试起来非常顺手。
评估模块一定不能省。训练循环里每过一定步数,就要在验证集上跑一次评估。有些模型收敛慢,loss还没降下来你就以为没救了;有些模型过拟合严重,训练loss很低但验证loss在上升。没有持续的评估,这些信号你都看不到。
4. 迈向生产:部署、监控与迭代
4.1 模型部署策略:三种主流方式
模型训练完不代表项目结束,模型上线服务才是工程真正开始的地方。部署方式我把它分成三种,按复杂度递进。
第一种是批处理预测。对实时性要求不高的场景,比如每日生成推荐列表、批量风险评分,可以直接用Airflow定时任务触发推理脚本,把预测结果写入线上数据库。这种方式的优点是简单可靠,天然适合重试和审计。
第二种是同步在线服务。用FastAPI包一个模型推理接口,接受请求、执行预处理、调用模型、返回结果。这种方式适合延时要求几十到几百毫秒的场景,比如搜索排序、实时风控。需要关注的内容包括接口限流、超时设置和优雅启动,模型文件要提前加载进内存,避免每次请求都重新载入。
第三种是流式服务。数据源是Kafka这类消息队列,模型以流处理的方式监听数据流,持续产出预测结果。这种方式适合日志实时分析和个性化推送,工程门槛最高,需要处理消息回溯、消费延迟和状态管理,初期项目不建议直接上。
4.2 监控:不只是看服务器指标
模型上线后,服务器CPU、内存、请求延迟这些常规监控当然要做,但AI工程特有的一些监控维度往往被忽略。
第一个是数据漂移检测。线上请求的数据分布和训练集分布不一致时,模型的预测能力就会打折。做法是周期性对线上特征做统计检验,比如PSI或者KS检验,当分布差异超过阈值就触发告警。这个机制能让你在业务指标变差之前,提前发现隐患。
第二个是预测分布监控。即使特征分布正常,模型的输出也可能因为内部状态变化而偏移。比如分类模型的类别概率整体升高,排序模型的分数均值异常。这类监控实现起来很简单,就是记录每次推理的预测值分布,定期观察。
第三个是业务效果监控。模型预测只是中间产物,最终要跟踪的是它对业务指标的影响。推荐模型要跟踪点击率,风控模型要跟踪召回率和误杀率。业务指标往往有滞后,所以需要设置合理的时间窗口,把它和离线指标关联起来。
4.3 持续迭代的闭环设计
AI系统的生命力来自持续迭代。模型上线不是终点,而是新一轮学习循环的起点。
我建议建立一个周级的迭代节奏。周一到周三分析上一版本的线上表现和用户反馈,周四和周五做实验和训练新模型,下一周择机发布。发布方式不要用全量替换,而是先让新模型跑一段时间影子模式,也就是只记录它的预测结果但不真正生效,对比它与线上模型的差异,差距收敛到合理范围再切换。
在数据层面,要把线上反馈自动回流到训练集。比如用户在推荐结果上的点击、不点击行为,风控系统的误报和漏报情况,都应该定期汇入下一版训练数据。这个反馈闭环越通畅,模型对业务变化的适应能力就越强,AI工程的“系统”属性也真正体现出来。
5. 常见问题与排查技巧实录
5.1 训练与推理效果不一致
这是我从零开始做AI工程时踩过的最深的一个坑。离线验证集指标很好,上线之后效果却很差,一开始我以为是模型过拟合,后来排查发现是特征计算逻辑不一致:离线训练用的是pandas处理,在线推理用的Java重写了一套,两边对于缺失值的填充方式不同,一个小数点级别的差异就把模型结果带偏了。
这类问题的排查思路很固定:选取线上真实请求的数据,用离线pipeline重新算一遍特征,和线上特征逐字段对比。哪个字段不一致,就说明哪个环节出了问题。为了根治问题,后来我把特征计算统一封装成一个独立服务,训练和推理都调用同一份代码,从此再没犯过这个错。
5.2 数据穿越:悄悄偷走模型可信度
数据穿越指的是训练数据里混入了未来信息。写特征代码的时候很容易无意中犯这个错。你的时间字段处理错了,用当天的数据算出了当天标签的特征,模型在训练时“偷看”了答案,离线指标好看得惊人,上线立刻现原形。
要识别这个问题,最有效的办法是做时间序列切分验证。把数据按时间分成三段:前60%训练,中间20%验证,最后20%测试。如果最后一段的模型效果大幅下降,数据穿越的可能性就很大。排查时关注每个特征的生成时间戳,确保特征里只用到了标签时间点之前的信息。
5.3 超参数不敏感?可能是优化器有问题
有时候你调整学习率、batch size,模型效果纹丝不动,看起来像“超参数不敏感”,实际原因可能是优化器配置有误。比如Adam优化器的学习率已经设到0.1,模型还能正常收敛,这时你可能已经掉进了梯度裁剪的陷阱里,梯度被限制得过小,模型根本感知不到超参数的变化。
我碰到过一次,loss下降非常平稳,但验证指标就是上不去。排查后发现问题出在损失函数权重上:我的多任务模型两个损失的数值量级差了100倍,梯度基本被大损失任务主导,小损失任务的权重更新几乎无效。解决办法是对两个任务的loss做归一化处理,分配合理的权重,模型效果才正常。
5.4 模型服务偶发超时
上线后的推理服务偶尔会出现超时告警,但大多数请求响应很快,这个问题很让人头疼。定位后发现是模型推理时的显存碎片化导致的。服务持续运行一段时间后,不同batch size的请求交替产生不同大小的显存申请,碎片累积使得偶尔一次的显存分配失败,出现了单个请求卡顿数十秒的极端情况。
解决方式是在服务启动阶段预先申请最大显存,用固定batch size执行推理,并定期重启工作进程,把显存碎片清理掉。这个经验说明一件事:AI工程的坑往往藏在工程细节里,而不在模型结构里。
| 症状 | 排查思路 | 常用解决方案 |
|---|---|---|
| 训练好但线上差 | 检查离线在线特征一致性 | 统一特征计算服务 |
| 离线指标异常高 | 怀疑数据穿越 | 按时间序列切分数据 |
| 超参数调整无效 | 检查优化器配置、损失量级 | 归一化loss、调整梯度裁剪 |
| 模型服务偶发超时 | 关注显存碎片和资源分配 | 固定batch、定期重启进程 |
6. 从零到一:给新手的三个落地建议
6.1 从最小可用闭环开始,不要贪大
刚接触AI工程的人总想把系统搭得又大又全:Kafka、Spark、K8s、监控告警一应俱全,结果基础设施折腾了一个月,模型效果还没见到。我的建议是,第一版系统越笨越好。用本地文件当数据源,用单机脚本训练,用Flask起一个最简接口,能跑通就算赢。
这个最小闭环的价值在于帮你建立“系统直觉”。当你看到数据从CSV文件流进模型,又变成API返回值输出时,你才真正理解了AI系统各组件之间是什么关系。在这个基础上加Kafka、加容器化、加自动化测试,每一次改动你都知道它在整个系统中处于什么位置,不会盲目。
6.2 多写坏代码,才知道好代码的价值
这条看起来像开玩笑,但我是认真的。抄模板写出来的机器学习代码,你永远不知道它规避了什么问题。亲手写一个没有做数据验证的训练脚本,让脏数据把训练过程搞挂一次,你才会理解数据校验模块的重要性。熬夜排过一次特征穿越问题,你才会重视时间戳设计。
所以从零开始学AI工程,早期不要追求工程“规范”。放心大胆地把数据加载写成一个函数,把训练循环写成一个大文件,把测试全部省略。踩坑之后,你自然会把数据类模块化、把配置抽离出来、把评估逻辑单独封装。这种由痛苦驱动的重构,比任何教程都有效。
6.3 保持一个“手工基线”
最后这一点是我最近几年最大的心得。不管算法模型做得多复杂,永远保留一个简单版本作为对照。这个基线可以是规则模型,可以是统计平均值,也可以是历史最优效果。每次新模型上线前,先跑一次简单基线,对比成本极其低,却能在第一时间暴露问题。
比如我做过一个文本分类项目,神经网络模型花了团队两周时间优化,准确率提升到90%。后来我随手跑了一个关键字规则版本,准确率居然也有85%。虽然最终线上用的是神经网络,但这件事让我明白,模型复杂度的收益必须通过和基线的对抗来验证,否则你很有可能在一个简单问题上过度工程化。
AI工程和算法竞赛不一样。竞赛只关心离线指标,工程关心的是系统在真实世界里稳定、安全、持续地产生价值。从零开始的过程,与其说是学习一堆工具和框架,不如说是训练自己用系统思维去拆解问题的能力。我踩过那么多坑之后最大的体会是,AI工程里所有复杂问题,最后都能追溯到某个基础环节没做好:数据没管好、特征没对齐、监控不到位、迭代没闭环。把这几个地基打好,剩下的技术选型、模型结构,都是锦上添花。