
看到 ai-engineering-from-scratch 这个标题点进来的朋友估计你的收藏夹里已经躺了不少AI学习路线图甚至刷完了上百集视频却还没有动手跑通过一个完整项目。如果你正好是这种状态这篇内容就是写给你的。这不是一份从入门到精通式的目录而是一个做过几年AI工程的人把从零开始最该走的路径、最该做的项目、最该避开的坑从头到尾串一遍。它叫AI工程而不是AI算法是有原因的工程意味着你要让模型在真实场景里跑起来、能维护、能迭代这件事和写好一个网络结构完全是两码事。下面这条路线是我自己带新人时实际用过的。它不激进、不炫技核心就一句话用最少的时间把全链路跑通再回到每个环节里补细节。整条路线从环境搭建、数学地基、经典机器学习、手动反向传播到一个完整的情感分析API最后落在一堆只有亲手做过才会踩到的工程细节上。1. 先别急着学算法AI工程到底在解决什么问题1.1 为什么大部分教程解决不了你的问题市面上关于AI的学习资料几乎都在讲怎么构建模型Linear Regression、CNN、Transformer、微调大模型。但真实的AI项目落地时模型可能只占整个工作量的三成。剩下七成是数据长什么样、模型怎么训练不动、上线之后指标为什么掉了、别人复现你的结果需要怎样的环境。这就是AI工程和AI算法的区别。算法研究员可以只优化一个paper里的创新点数据工程师可以只负责管道但AI工程师得把整条链子串起来从原始数据出发清洗、标注、特征提取、训练、评估、打包成服务、监控线上效果再根据反馈迭代下一版。任何一个环断裂模型再漂亮也上不了线。我给新人做引导时喜欢用一个造车的比喻模型是发动机AI工程是整车。你光有一个狂暴的发动机没有底盘、转向、刹车车子照样不能上路。反过来一个普通的发动机在成熟的整车架构里反而能稳定跑很久。1.2 四个能力象限学完之后你应该具备什么如果你接受AI工程 系统工程这个前提那么学习目标就清晰了。我把它拆成四个能力象限每次学习一个项目时都可以对照这个表看看自己缺哪块能力维度具体内容常见误区数据能力采集、清洗、采样、标注策略、特征工程、数据版本管理以为数据集是现成的拿过来就能训模型能力经典机器学习与深度学习原理、损失函数、正则化、评估指标以为会用框架就是会模型训练能力实验追踪、超参调整、GPU资源管理、可复现性以为训练只是点运行按钮交付能力API封装、容器化、上线部署、监控告警、持续迭代以为模型文件交给后端就行后面几章的内容都是围绕这张表展开的。先把框架记在脑子里学习的每一步步都会变得有目的。2. 地基部分数学和Python建议按需补而不是从头啃2.1 别被高数劝退只需要三门课的最小可用版本很多人一谈AI先想起数学然后被厚厚的教材劝退。我的观点是高等数学可以作为长期课慢慢修但起步阶段你想要跑通AI工程只需要三门课的最小可用版本。第一是线性代数。核心是矩阵乘法、矩阵形状对应关系、乘法的物理意义。你就把矩阵乘法当作批量计算多条线性组合的工具输入是一个向量权重是一个矩阵相乘就是对输入做了一次线性变换。神经网络里的h W x b本质就是这句话。第二是概率统计。重点关注分布、期望、方差、条件概率、最大似然。你不需要会推导复杂的概率公式但看到模型输出概率时要清楚它含义是什么看到训练集和测试集分布不一致时要能意识到问题。第三是微积分。核心就两个导数和链式法则。导数告诉你参数往哪个方向调能让损失下降链式法则告诉你误差怎么从输出层一层层传回输入层。这些概念用30页不到的讲义就能说清楚不需要先修完一学期的微积分。2.2 一个干净的学习环境比多装100个库重要Python环境是零基础同学最容易翻车的地方。很多新手图省事在系统Python里直接pip install装到一半权限报错、版本冲突、依赖损坏最后放弃。我给的建议是用venv或conda给每个项目单独建虚拟环境。一个项目一个环境环境里只装这个项目需要的东西。这看起来像多此一举但等你五六个项目并排躺着一个环境一套依赖出问题重装也只是几分钟的事而不是把系统环境搞得一团糟。起步阶段需要装的库很少numpy、pandas、matplotlib再加一个jupyter就够了。这三个库是数据分析的基础设施numpy管数值计算、pandas管表格数据、matplotlib管可视化。深度学习框架先别急着装等把原理算法手写过一遍回头装框架你会更清楚每条API在做什么。2.3 第一个代码任务用梯度下降实现最小二乘线性回归选这个任务当开局是因为它能用最少的代码把数据-模型-损失-优化四个概念串起来。不用任何机器学习库只需要numpy。数据是一组带噪声的线性点我们要让一条直线去拟合它们。import numpy as np np.random.seed(42) X np.random.rand(100, 1) * 10 true_w, true_b 2.5, -1.0 y true_w * X[:, 0] true_b np.random.randn(100) * 2 w, b, lr 0.0, 1.0, 0.01 for step in range(501): y_pred w * X[:, 0] b loss np.mean((y_pred - y) ** 2) grad_w np.mean((y_pred - y) * X[:, 0]) grad_b np.mean(y_pred - y) w - lr * grad_w b - lr * grad_b if step % 100 0: print(fstep{step:03d}, w{w:.3f}, b{b:.3f}, loss{loss:.4f}) print(f拟合结果: w{w:.3f}, b{b:.3f} | 真实值: w{true_w:.3f}, b{true_b:.3f})跑完这段代码你会直观感受到loss在不断下降w和b慢慢逼近真实值。这就是机器学习最核心的动作——根据梯度更新参数没有黑魔法。我要求每个新人把这个过程亲手跑一遍并且把lr从小到大改几个值看收敛速度怎么变化、过大的学习率如何导致发散。这个操作会在你脑子里钉下一枚钉子梯度下降需要合适的学习率后面用深度学习框架时看训练曲线会有完全不同的理解。3. 手动实现一次反向传播胜过刷十遍教程3.1 经典机器学习是深度学习的语法很多从零开始的朋友嫌经典机器学习没用——逻辑回归、决策树、随机森林这些在老生常谈里显得不酷。但我不建议跳过它们原因是经典机器学习用最朴素的方式让你理解机器学习里的通用概念这些概念放到深度学习里一个都不会过时。给你一张对照表感受一下就明白了经典ML概念深度学习对应特征工程手动构造表示学习模型自动学正则化L1/L2weight decay、dropout交叉验证训练集/验证集/测试集划分梯度下降SGD、Adam等优化器偏差-方差权衡过拟合与欠拟合类别不平衡处理采样策略、损失函数加权我在带人做第一个经典ML案例时常用零售销量预测给定历史日期、节假日、商品价格、促销信息预测销量。特征做起来直观数据量也不大跑完能快速看到模型效果和特征重要性排序。这个过程会把数据清洗-特征工程-交叉验证-模型选择-指标评估完整走一遍走完后你会发现深度学习的各个环节全都似曾相识。3.2 手工推一遍MLP的反向传播接下来是很多人觉得最难、其实最值得做的一步不用任何深度学习框架纯numpy实现一个微型多层感知机手动完成一次反向传播。这个例子我固定用三层结构输入2维、隐藏层3个神经元、输出1个。损失函数用均方误差。代码如下import numpy as np def sigmoid(x): return 1.0 / (1.0 np.exp(-x)) x np.array([1.0, 2.0]) y_true 1.5 lr 0.1 np.random.seed(0) W1 np.random.randn(3, 2) b1 np.zeros(3) W2 np.random.randn(3) b2 0.0 # 前向传播 z1 W1 x b1 h sigmoid(z1) out float(W2 h b2) loss (out - y_true) ** 2 # 反向传播从损失开始往前倒推梯度 d_out 2.0 * (out - y_true) # 输出层梯度 d_W2 d_out * h # W2 梯度 d_b2 d_out d_h d_out * W2 # 误差传回隐藏层 d_z1 d_h * h * (1.0 - h) # sigmoid 导数 d_W1 np.outer(d_z1, x) # W1 梯度 d_b1 d_z1 # 参数更新 W2 - lr * d_W2 b2 - lr * d_b2 W1 - lr * d_W1 b1 - lr * d_b1这段代码一次前向、一次反向、一次更新就把整个梯度下降的循环展开了。你一定亲手敲一遍不要复制。敲的时候留意每一行代码的形状W1是 (3,2)x是 (2,)z1是 (3,)W2是 (3,)h是 (3,)out是标量。形状能对上反向过程就通了一半。这在深度学习里叫形状直觉。我见过太多人用PyTorch或者TensorFlow时反复报形状不匹配的错但就是看不出问题在哪。根源就是没理解每一中间变量该是什么形状。手动写一次反向传播这个病能在一天内治好。3.3 从手写版本过渡到PyTorch手写完反向传播后再去看PyTorch的教程效率会高很多。你看到loss.backward()时会知道它背后替你算的就是刚才那一堆矩阵导数和链式法则看到optimizer.step()会知道它做的事情就是w - lr * grad。框架只是把底层重复劳动自动化了并没有发明新的数学。建议这个阶段用PyTorch重新实现刚才的MLP再引入真实数据集比如sklearn内置数据集体验一下用框架单机训练一个分类模型的完整循环。你不需要马上碰Transformer先把手写的三层网络和PyTorch的nn.Linear对应上建立程序里的每一行代码都有数学含义的连接。4. 第一个端到端项目做一个中文情感分析API4.1 项目选型为什么是情感分析理论学习一段时间后一定要做端到端项目。什么叫端到端从原始数据到最终一个外部可调用的服务中间每一步都要自己走通。我推荐第一个项目做中文情感分析原因有三个第一数据好拿。公开的中文评论、影评、商品评价数据集中就有不少不需要自己建采集管道。第二任务直观。判断一段文本是正面还是负面效果好不好一眼就能看懂不需要专业背景。第三模型选择灵活。你可以从TF-IDF加逻辑回归这种经典方案起步再往上升级到BERT全家桶中间可以对比的维度非常丰富。这个项目做下来你会同时碰到数据、训练、部署、评估四个领域的问题正好覆盖前面说过的能力象限。4.2 数据准备先把样本看一遍再动手很多人拿到数据就开训这是大忌。我要求自己和新手都必须先做一步人工抽样检查随机打开两三百条样本读一遍记录脏数据的类型。常见问题包括重复样本、表情符号和HTML标签、繁体字和简体字混用、文本里夹带URL、标注错误。这些都会实实在在地影响训练效果。清洗的最小操作是去重、去除明显广告/无意义文本、统一简繁、把URL和邮箱替换成占位符。如果文本短到只剩几个字也要考虑是否保留。然后做训练集、验证集、测试集的划分。这里请一定记住暴守原则先划分再预处理。如果你先对整个数据集做了清洗、标准化再划分训练集的信息就会悄悄渗进测试集测试指标会虚高这就是数据泄漏后面第5章我会专门讲。4.3 训练与实验记录先有基线再谈优化第一个版本建议用最简单的方案做基线TF-IDF向量化 逻辑回归。它的训练时间以秒计却能把文本分类的完整逻辑跑通。虽然效果大概率不如BERT但它是你后面所有模型对比的基准线。训练时每个环节都要留下记录。我见过最多的情况是前几天跑的模型当时觉得效果还行但没记超参数后面想复现却完全想不起来跑过什么了。所以从第一个项目开始就要养成实验记录的习惯。最轻量的方式是用MLflow或简单到dict里记录每轮的超参、指标、模型文件名。mlflow run . mlflow ui像上面两条命令跑完mlflow ui会在本地启动一个页面每次实验的训练损失、验证集F1、超参数都会自动沉淀下来。这个习惯刚开始觉得麻烦但等你同时试十组参数的时候就会感谢当初的自己。4.4 部署把模型封装成API训练完成的模型文件只是模型还不是服务。要让它被别的系统调用我们需要封装成一个HTTP接口。这里我推荐FastAPI加Docker这套组合FastAPI写接口简单、自带接口文档Docker解决环境复现问题。from fastapi import FastAPI from pydantic import BaseModel import joblib app FastAPI() model joblib.load(models/sentiment_lr.joblib) vectorizer joblib.load(models/tfidf.joblib) class ReviewText(BaseModel): text: str app.post(/predict) def predict(review: ReviewText): vec vectorizer.transform([review.text]) prob model.predict_proba(vec)[0] return {text: review.text, positive_prob: float(prob[1])}这个接口接收一段文本返回一个正面概率。本地跑uvicorn启动服务后用curl或者浏览器访问docs页面试一下。这一步的意义是把模型从notebook里的一个变量变成别人可以直接调用的服务工程化从这一步才真正开始。服务跑通后随手补一个Dockerfile把模型文件和代码一起打包成镜像FROM python:3.10-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY app/ ./app COPY models/ ./models EXPOSE 8000 CMD [uvicorn, app.main:app, --host, 0.0.0.0, --port, 8000]打包成镜像的意义在于可复现。换一台机器、换一个人只要同一个镜像跑出来的就是同一个服务。这解决了AI项目里最大的混乱来源之一环境不一致导致的结果不一致。5. 真正拉开差距的五个工程细节5.1 数据泄漏最隐蔽的模型作弊数据泄漏是指训练过程中模型看到了本不该看到的测试集信息导致评估指标虚高。最常见也最容易犯的一处是做缩放或编码时先对整个数据集拟合再划分。比如你用StandardScaler()把全部数据标准化然后随便划分。标准化过程会用到全量数据的均值和方差等于测试集的分布信息已经混入训练阶段测试指标的参考价值就打了折扣。正确做法是先train_test_split再在训练集上fit预处理器然后在训练集和测试集上分别transform。同样的坑还会出现在时间序列数据上如果你用未来的数据计算滚动均值作为特征模型在训练时就已经看到了未来回测表现会漂亮得离谱上线后立刻失灵。这类问题不容易成交警只能靠多问一句这个特征在预测时刻真的可以得到吗来预防。5.2 类别不平衡准确率会骗人情感分析如果数据比例是9:1模型全预测为多数类准确率都有90%。所以在分类任务里我几乎不看准确率重点看查准率、查全率、F1和混淆矩阵。尤其对少数类查全率往往比查准率重要得多在垃圾评论拦截场景里放过一条负面评论可能比误杀一条正常评论代价更大。处理类别不平衡的一般顺序是先考虑换评估指标再看是否需要调整采样。简单改一下class_weightbalanced很多分类器就自带采样可以用过采样、欠采样更进阶的方法包括损失函数加权。记住不先定义什么错误最贵就谈不上怎么平衡。5.3 分布漂移训练集和线上数据不是一回事你训练时用的是历史数据上线后线上来的样本却每天都在变。用户聊天风格变了、新词出现了、点击行为漂移了。这是AI工程最现实的问题之一也是教程里最少被提到的。初级的监测方法是把线上推理的输入特征分布记录下来和训练集特征分布做对比。比如文本长度分布、词覆盖比例、预测概率的分布一旦偏差超过阈值就告警。更高阶的做法是定期用少量人工标注的线上样本回归评估模型。这个能力要在第一个项目里就埋下种子——推理服务里加一行日志记录输入和预测分布成本很低价值很高。5.4 环境复现今天能跑不代表明天还能跑我的第一个深度学习项目遇到过最荒谬的事三个月前训练好的模型换了台机器重训效果对不上折腾两天发现是numpy版本升级了导致某个随机行为变了。深度学习版本依赖的敏感程度超出很多新人的想象。从项目第一天起就锁依赖版本。requirements.txt里不要写numpy1.20而是写死具体版本numpy1.24.3。加上Docker镜像后这个问题就能从根上解决镜像标签本身就是一份完整的依赖快照。5.5 模型上线只是开始不是结束模型部署成API后很多人觉得任务完成了。但AI工程恰恰是上线才刚开始。你要监控响应时间、错误率、请求量更重要的是监控预测置信度分布。如果某天线上平均置信度开始异常波动往往预示着输入分布已经变化。我建议在每个推理服务中记录三样东西输入摘要、预测结果、置信度。只要有这些日志后续做离线评估、数据归因、迭代训练就都有原材料可用。没有日志的模型服务等于黑盒上线出问题时你连从何排查都不知道。6. 我对从零开始的几个重新理解走到这里想聊几句我踩过坑之后的体会也不算总结就是一些实实在在的建议。第一收藏夹不是知识库。很多人收藏了几十篇教程却始终停在第一步。AI工程是手艺活手不从键盘上过知识永远不属于你。我见过最快的同学不是因为聪明而是因为每天固定写两个小时代码雷打不动。第二路线图只要一份但一定要走完。市面上路线图多到爆炸每份都覆盖几十个主题。你不需要全部看完你要的是从数据到模型到上线完整走一遍把全链路打通。第一个项目可以粗糙但不能缺环节。第三遇到环境问题不要硬扛。装不上依赖、版本冲突这类问题十有八九是环境混乱最好的解法是新建一个干净虚拟环境重来而不是在乱环境里反复调试。我刚入门时在这上面浪费过大量时间现在只要感觉不对劲就先搞环境。第四先跑通再优化。我见过新手把大量时间花在调参上却忽略了模型训练数据里十几万条重复样本。先做干净数据和简单基线把指标记录下来再考虑换模型或者加特征。多数情况下数据质量带来的收益远大于模型结构的微调。如果你正要从零开始学AI工程不需要一次性消化所有内容。照着前面几章的路径先搭环境再手写一遍线性回归和反向传播然后动手做那个情感分析API把端到端流程完整跑通。过程中遇到问题回到对应的章节看看再不行就动手查日志、翻文档。这条路不难找难的只是迈出第一步。