
标题里的ai-engineering-from-scratch翻译过来就是“从零开始学AI工程”。做了这么多年AI engineering相关的工作我最大的感受是能把一份数据变成一份报告的人很多能把一个模型变成一项稳定服务的人很少。很多朋友私信问我怎么从零开始学AI工程不是学算法原理那种而是真正能落地的那种。这篇内容就是把这些年攒下的经验梳理清楚写给两类人——准备转行进AI开发的人以及已经在一线做算法却一直被工程问题困扰的工程师。先明确一个目标这篇文章不是带你复现某个SOTA算法而是帮你把“实验代码”升级成“工程系统”。你会接触到的关键环节包括数据管道、训练运维、模型部署、监控反馈、版本追溯。如果说算法是汽车的引擎AI工程就是整台车——底盘、变速箱、仪表盘、刹车系统缺一样都跑不起来。文章里会穿插我实际做项目的案例也会把那些文档里不写、组内老人才知道的坑挖出来。1. 先认清AI工程和算法调参是完全不同的两码事1.1 算法课教的是“让模型更聪明”工程课教的是“让系统更可靠”写代码训练模型这个叫机器学习。把模型放到业务里长期稳定地运行这个叫AI工程。这俩的考核标准完全不一样。算法实验阶段你关注的是loss有没有下降、准确率是多少、能不能超过baseline。到了工程阶段你关注的是接口响应时间有没有达标、并发上来会不会OOM、模型输入数据突然多了一个字段怎么办、线上效果两周后为什么下降、模型出问题能不能一键回滚。同一套模型在不同阶段面对的完全是两种问题。举我自己做过的例子。之前给一个业务方做过用户流失预测notebook里跑出来AUC大概0.87当时觉得还不错。结果上线的时候问题一个接一个业务方的数据仓库里字段和训练时的字段对不上、某些用户只有一条记录但特征工程却要求窗口期数据、上游表凌晨才更新导致白天请求量大时特征缺失。这些问题没有一个靠调参能解决全是工程问题。所以你在看任何AI工程学习路线时第一个要确立的认知就是技术栈里有一半的东西与神经网络无关。相反它和分布式系统、数据库、容器化、监控告警、CI/CD这些东西强相关。这也是为什么很多数学很强的朋友反而做不好AI工程——因为工程能力的核心不是推导公式而是面对一台不稳定的系统时能快速定位和恢复。1.2 从零开始的人最容易踩的三个认知误区我接触过很多从零开始的人发现有几个误区特别容易把人带偏。冲动型一头扎进深度学习框架的教程里学了一堆网络结构然后问“我是不是该先学三个月数学再去碰项目”。数学当然重要但如果永远停留在准备阶段你永远不会知道真正的问题是什么。建议方式是用最小可用的流程先跑通一个项目遇到数学问题再针对性地补。AI工程不是数学考试是动手能力考试。盲目型以为工程化就是调参或者以为只要租几块GPU、把模型训练完就算大功告成。实际上数据管道、评估体系、部署链路的比重远超模型训练本身。我见过很多人花一个月调模型效果提升2%但后来把数据清洗做好一次性把指标拉高了10%。短视型以为部署就是给模型用Flask包一层接口。等真的上线就会遇到模型加载复用、推理超时、版本兼容、特征管道一致性、监控告警、灰度发布等等问题。这些细节我在第5章详细说这里先提醒部署是最能撕开你认知缺口的一环。如果只能带走一条认知我希望是这一句AI工程不等于模型训练它是一条包括数据处理、训练、评估、部署、监控的完整流水线你的工作就是让这条流水线高效稳定地运转。2. 动手之前把环境、工具链和第一个端到端样例跑起来2.1 环境准备里最容易忽略的版本一致性零基础起步的人做环境准备最常见的情况是跟着教程一步步装包结果折腾一整天。我给你的建议很直接先锁版本再装环境。我自己通常用一个组合conda创建虚拟环境Python固定到3.10CUDA版本和框架版本提前对齐依赖用requirements.txt锁定具体版本。为什么要这么较真因为版本不一致带来的报错非常隐蔽。你在自己机器上跑得好好的notebook推到服务器上突然报错最后发现是本地的scikit-learn版本比服务器高一个小版本接口行为变了。这类问题在团队协作里几乎每周都能碰上。如果你是做什么视觉或者NLP任务的还要特别留意GPU驱动和CUDA版本。建议训练之前先跑一条类似torch.cuda.is_available()的检查命令别等训练跑到一半才发现在用CPU。条件允许的话强烈建议从第一天就用Docker来固定开发环境。把基础镜像、依赖列表写进Dockerfile训练和推理都用同一份镜像能避免大量“在我电脑上明明可以”的扯皮。Docker是AI工程的第一个基本功不是可选项。虽然开始用会觉得多了一步操作但坚持两周你就会发现好处。2.2 第一个端到端样例应该选什么任务很多教程会让你用MNIST开始它当然能帮你熟悉框架语法但我的建议有点不一样第一个端到端样例选一个和你未来想做的业务方向更接近的结构化数据任务。拿“客户流失预测”举例这个任务麻雀虽小五脏俱全。数据里有数值特征、类别特征、时间特征有缺失值需要处理有类别不平衡需要设计评估指标还是一个典型的二分类问题。你可以用大概几百到几千条样本完整地走一遍下面的流程读取数据做基本探索性分析。数据清洗和特征工程。划分训练集、验证集、测试集。训练一个模型刚开始用LightGBM或逻辑回归都行。在测试集上评估画出关键指标。保存模型文件。写一个简单的HTTP接口加载模型并返回预测结果。用一条新数据请求这个接口验证结果。这个流程看起来简单但如果你能全部走通你就已经具备了AI工程一半的基础能力。难点不在于每一步都高深而在于每一步你都亲手做了一遍。我见过太多人只做到第5步后面“保存、加载、接口化”完全没有概念于是模型永远只能活在notebook里。我自己后来做趣味项目时也坚持用这个流程哪怕只是一个简单的文本分类也一定把接口封起来测试一遍。这个习惯帮我避开了很多烂尾项目。2.3 开发流程里必须建立的四个习惯我总结过四个习惯如果能较早养成后面会省很多事第一用Git管理代码而且从第一天就用分支开发别永远在main上改来改去。哪怕只有你一个人分支也能保护你的实验过程不被破坏。第二项目目录结构清晰。我常用这样一个结构project/ ├── data/ # 数据原始数据和加工后的数据分开 ├── src/ # 实际代码模块训练/评估/推理分开 ├── configs/ # 配置文件与超参数 ├── notebooks/ # 探索性分析不放生产代码 ├── scripts/ # 命令行运行入口 ├── tests/ # 单元测试和接口测试 └── README.md这个结构不是死的但有一个原则生产代码和探索代码分离。你可以在notebook里自由探索但最终上线的东西必须移到src下面变成可以被调用、测试的模块。第三每次实验都留下日志。不用花哨至少包含数据版本、超参数、模型结构、训练耗时、评估指标、模型文件路径。第四写README。记录这个项目要解决什么问题、怎么跑通、关键结论。很多人觉得写文档浪费时间但当你三个月后回过头看自己项目或者有新人要接手时就知道README有多重要了。3. 数据这关过不去后面全是花架子3.1 数据获取与标注AI工程里最耗时间的部分如果你以为AI工程的重心在训练模型那数据会教你重新做人。我在真实项目里面对的数据和Kaggle上漂漂亮亮的csv完全是两回事。真实数据通常分散在十几个表里字段名起得随心所欲缺失值、重复值、异常值到处都是最麻烦的是标签往往要靠人工定义和标注。AI工程师的大部分时间其实是在处理这些事情。我当时做流失预测项目光是梳理业务口径、清洗数据、构造标签就花了两周。后面训练加调优只花了一天。你可能会觉得比例夸张但真实项目就是这样数据工作没做完之前模型根本没有高质量的食物可以吃。如果你是从零开始学建议别逃避这一步。手动构造一个带脏数据的小数据集然后练习清洗流程。这个流程包括去重、处理缺失、处理异常、类型转换、构造标签、划分数据集。每一步都值得亲手写一遍因为面试或者实际项目里问的就是这些。3.2 数据质量检查把异常消灭在训练之前数据清洗的下一步是建立一套数据质量检查机制。你别把希望寄托在“人多看几眼数据就能发现问题”实际数据量大、维度多肉眼根本看不过来。我通常在训练之前写一个数据校验脚本检查几个核心项字段缺失率发现某些关键字段缺失超过阈值就告警。字段类型确保数字、日期、ID没有被解析成错类型。取值分布和上一周期对比发现分布异常波动。标签泄漏检查这是最容易踩的坑。标签泄漏值得单独说。所谓泄漏就是你把“未来信息”或者“不应该在预测时出现的信息”放进了训练特征里。比如你要预测用户未来会不会流失结果特征里包含了“用户是否已经申请退订”这个字段——它在决策时点根本不应该存在。训练时你会得到一个非常漂亮的指标上线后指标立刻崩掉。这种问题连资深工程师偶尔都会犯所以最好在数据校验脚本里专门做一轮思考每个特征在预测时刻是不是真的拿得到拿得到才算合法特征。3.3 数据版本化让模型绑定到具体数据好现在你已经有个干净可用的数据集了。下一步很多人会忽略给数据一个版本。为什么需要数据版本化你的模型训练好之后必须能回答一个问题我是用哪份数据训练出来的。上线后效果不好你要排查是模型问题、代码问题还是数据问题。如果数据没有版本你连回溯的起点都找不到。做法不一定要很重。小项目里最简单的方案就是给数据集打上带时间戳的版本标签同时计算一份哈希值作为数据指纹写进实验记录里。等到项目规模变大、数据频繁更新时再用专业的数据版本管理工具比如DVC这类能记录数据集快照的方案。我自己习惯的规则每次数据变更都生成新版本号并且绝不覆盖旧版本。旧数据丢了的痛苦谁经历谁知道。4. 训练模型不是炼丹是带着指标在做系统调试4.1 把训练流程脚本化拒绝反复复制粘贴训练这个环节最容易犯的问题是流程不规范。很多人是打开notebook从上往下跑一遍跑通了就完事。问题是你下次想用别的数据集跑一遍只能复制粘贴改路径你想固定随机种子才能复现结果结果忘了设置训到一半挂了又得从头跑。工程化的做法是把训练变成一条脚本命令。你写一个train.py用命令行参数传递数据路径、配置路径、输出路径。脚本内部做这些事固定随机种子、加载数据、创建模型、定义优化器和损失函数、训练循环里按时记录损失和指标、验证集上评估并保存最优checkpoint、早停机制防过拟合。写脚本是一件一劳永逸的事。之后每一次实验你只需要改配置文件里的超参数然后执行同一个命令。你会明显感觉到实验从“手忙脚乱”变成了“流水线作业”。这也是从练习者到工程师的转变标志之一。4.2 评估指标的选择直接影响项目走向很多人一开始习惯用准确率这个指标很直观但在很多实际场景里会骗人。比如你做一个欺诈检测正样本只有1%你把所有样本都判成负样本准确率都能有99%。这个模型有用吗一点用都没有。所以评估指标得根据业务场景来选。二分类问题里除了准确率至少要看精确率、召回率、AUC。类别分布严重不平衡时我一般重点看PR-AUC或F1。回归问题则要区分MAE和RMSEMAE更直观RMSE会放大离群点的影响看你的业务更关心哪种错误。更关键的一个习惯是把技术指标和业务指标分开看。模型AUC高不代表业务收益就一定能提升。比如流失预测里模型找出一批高流失风险用户但运营有没有能力承接干预这些用户如果承接不了技术指标再漂亮也落不了地。做AI工程你得习惯跟业务方一起定义什么叫“真正有用”。4.3 实验跟踪是你唯一的进度条模型训练像做一项长跑实验。今天你试了A方案明天试B方案一周后你已经记不清A和B的差别在哪里了。如果只用“名字日期”存模型文件你会很快迷失。所以我一直强调实验记录结构化的价值。你需要一张实验表至少包含这些字段实验ID、数据集版本、关键超参数、模型结构、训练时间、评估指标、模型文件路径、备注。你可以用一个Excel表记录也可以一开始就用上实验管理工具MLflow、WB都行如果怕太重自己先写个CSV记录器也完全够用。我刚入行时是手动记录后来项目多了、实验频繁了果断上了实验管理工具。因为它的好处不只是记录还能把模型文件、指标、配置直接关联在一起回看结果和复现实验都方便很多。这一条建议属于我“如果能早点做就好了”排行榜的前三名。4.4 训练常见问题速查这里列几个我遇到最多的训练期问题以及对应的排查顺序给你做个速查表。现象优先排查方向常见解决办法loss始终不降数据归一化、学习率、代码bug调学习率、标准化输入、检查训练脚本严重过拟合验证集指标远差于训练集加正则、加数据增强、早停、减模型容量训练结果波动大随机种子、数据shuffle固定种子、固定shuffle顺序GPU显存不足batch size过大调小batch、梯度累积、混合精度训练指标高但线上崩标签泄漏、训练/推理分布不一致检查特征合法性、检查数据漂移每一行背后都有真实项目教训。比如“指标高但线上崩”我至少遇到过三次每次排查到最后都绕不开数据问题。所以遇到诡异现象先查数据再查模型最后查代码这个顺序能节省很多时间。提示训练阶段永远保留一份“当前最优实验结果”的完整记录。很多人模型训出来很兴奋回头要复现的时候才发现当时用的数据版本和参数都记不清了。这条记录习惯会省下你无数个加班的夜晚。5. 模型能用只是开始部署上线才是真正的分水岭5.1 从模型文件到可用的服务中间隔着一个推理封装模型部署这个词听起来挺吓人但把它拆开看核心问题就两个怎么把训练好的模型稳定地加载起来怎么把外部请求正确地变成预测结果。先说加载。最明显的一个新手错误是在每一次请求里都重新加载模型。模型文件小的话还好稍微大一点加载耗时就能让接口超时。正确做法是在服务启动时加载模型把模型对象放在内存里后续请求直接复用。然后是推理封装。这里有个特别容易忽略的点训练时做的数据预处理和特征工程推理时必须完整复刻。训练时你用了缺失值填充、标准化、类别编码推理时少了任何一步预测结果都是错的。给你一个最小但规范的推理服务示例框架用FastAPIfrom fastapi import FastAPI from pydantic import BaseModel import joblib import numpy as np app FastAPI() model None class Item(BaseModel): feature1: float feature2: float feature3: float app.on_event(startup) def load_model(): global model model joblib.load(models/latest/model.pkl) app.post(/predict) def predict(item: Item): if model is None: return {error: model not loaded} features np.array([[item.feature1, item.feature2, item.feature3]]) pred model.predict(features) return {prediction: int(pred[0])}这个示例很小但它的结构是对的模型启动时加载、输入有格式校验、预测结果统一返回。真实项目还会加上日志、鉴权、错误处理但核心骨架就是这个思路。提示新版FastAPI推荐用lifespan机制替代app.on_event(startup)来管理启动逻辑。这里用on_event只是为了把代码保持在小篇幅内你自己写工程代码时建议用lifespan可读性和生命周期控制都更好。5.2 性能与稳定性并发、延时、预热与容错接口能跑通只算完成了一小半。接下来你要回答一个更关键的问题并发上来的时候它还能不能正常工作我第一次把模型服务上线时单机压测没有任何问题结果联调时并发一上去接口就大量超时。原因是模型单次推理时间慢请求排着队等待服务线程一旦耗尽新请求全部被阻塞。后来做了三件事才缓解降低单请求耗时、增加服务实例、逻辑上做超时控制。对新手来说我建议的顺序是先保证正确再做性能优化能不碰底层加速就先不碰。在保证正确的基础上用压测工具模拟几百个并发请求看两个指标TP99延迟和错误率。如果延迟过高再做优化。模型推理加速有一些常见手段把模型转成ONNX或TensorRT格式、做权重量化、开启GPU批处理、加缓存层。但这些手段都会引入新的复杂度和陷阱所以我把建议放在这里等你的服务真正跑起来、监控数据清晰了再考虑动这块。5.3 监控模型不是上线就结束了模型上线那天不是终点恰恰是麻烦的开始。很多从零开始的朋友以为上线成功后工作就结束了但做AI工程的人都知道上线只是把问题从“训练期”搬到了“运行期”。你需要盯着的东西包括接口错误率、响应时间、请求量、模型预测的类别分布。但还有一个专门针对模型的问题要盯叫数据漂移。举个具体例子你训练模型时用户年龄分布在18到45岁上线两个月后业务做了调整流入的用户年龄段变成了40到60岁。模型没见过这种分布预测自然不准。你如果没有监控可能要等业务投诉了才会发现。如果你有监控写一个定时脚本比较线上输入分布和训练分布的相似度阈值一超就告警就能把问题消灭在萌芽期。这里才是MLOps真正施展拳脚的地方。很多人觉得MLOps是运维的事其实对一个AI工程师来说监控意识直接决定了项目能不能长期存活。6. 可复现与版本控制工程素养藏在细节里6.1 代码、数据、模型、环境四个维度都要有版本如果说从零到一跑通项目的能力决定了你能不能入门那版本管理能力决定了你能不能在团队里长期立足。AI项目里有四个东西都在不断变化代码、数据、模型、环境依赖。任何一个变了实验结果都可能不同。所以四个维度都要有版本意识。代码有Git管这个大家都熟。数据版本我在第3章讲过了。模型方面建议每个实验产物放到模型注册表里用“版本号实验ID指标”命名做到关键指标变化时能一眼看出来是哪个实验的文件。环境方面用requirements.txt或镜像固化依赖版本。一个完整的可复现记录至少要能把这四件事对齐到同一时间线某次实验用了哪个commit的代码、哪个版本的数据、哪个实验配置、哪个环境镜像。有了这条时间线你才可以回答“三个月前那个模型是怎么训练出来的”这种世纪难题。6.2 让实验结果可以被任何人复现可复现不是为了应付检查它本质上是一种协作能力。我刚工作那会和同事对接实验对方发一个“final_model.pth”过来问他这个模型用什么数据、什么参数跑的回答是“忘了”。那一刻我就明白了AI工程里最值钱的东西不是哪个模型文件而是让模型能被复现的整套上下文。所以我的习惯是训练脚本里固定随机种子、读取统一的数据加载函数、把超参数写到config文件里、训练结束自动记录实验摘要。这样一来任何同事拿到我的代码按README跑一遍就能得到差不多的结果。就算不能完全一致也不会差到十万八千里。这一步的意义往小里说是个人的好习惯往大里说它就是AI工程和算法研究之间的分界线。实验室里可以凭感觉做实验工程系统里不允许。7. 给真正想从零开始的人路线节奏和避坑清单7.1 三个月路线建议最后聊一下时间和节奏。很多人问“从零开始学AI工程要多久”我给一个比较现实的参考——三个月每天投入两个小时以上可以达到“能独立上线一个小项目”的水平。第一个月跑通基础。主要做三件事搭好环境、选一个端到端样例完整跑通、养成记录实验和用版本控制的习惯。这个阶段的目标是“不慌”遇到问题知道去哪里查、怎么排查。第二个月部署和优化。把模型服务化用压测工具测性能学习怎么处理并发问题。这个阶段目标是把服务从“能用”变成“勉强扛得住”。再补充一点模型推理优化的知识不用太深入能说出几种方法就行。第三个月完善工程闭环。做数据版本化、实验跟踪、监控告警、基础CI/CD。目标是把项目当成一个真正的产品来对待和代码、数据、模型、运行状态的完整周期打交道已经比较习惯。7.2 我踩过的坑希望你别踩最后把我自己踩过的坑分享出来算是替大家提前交学费。第一迷信复杂模型。小数据集、简单问题上LightGBM比大模型更稳而且部署成本低得多。先上简单方案再根据业务需求升级不要一上来就追求花活。第二忽视数据漂移。模型上线之后前两周效果很好第三周开始用户反馈变差一查是上游数据口径变了。这个教训让我从此把监控当第一优先级。第三不做灰度就全量上线。模型服务出问题影响面太大第一次务必用一小部分流量验证确认稳定再放开。第四过度追求指标。AUC从0.86调到0.87花了一周实际上业务方根本不关心这0.01他们关心的是客户干预的转化率。把精力放到能产生真实价值的环节上。第五只写notebook不写工程代码。等你需要把项目交给别人维护的时候只有代码和文档能替你说话。notebook不是交付物它只是草稿纸。我从零开始学AI工程的过程走了很多弯路上面这些经验都是真金白银换来的。如果让我再重新来一次我会把顺序反过来先跑通端到端再回头补理论先把一个简单项目上线再研究复杂算法。这条路没有捷径但最笨的路往往最稳。希望你也能早点把第一个模型真正“跑进生产环境”那才是你真正踏入AI工程门槛的时刻。