ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

AI工程从零构建:从手写算法到部署监控的完整路径

AI工程从零构建:从手写算法到部署监控的完整路径 很多搞AI的朋友都问过我一个问题“ai-engineering-from-scratch”这个方向到底该怎么入手市面上铺天盖地的都是“三天上手大模型”“五分钟微调Llama”但真要自己从零搭一套完整的AI应用大多数人都卡在半路。这个项目标题本身其实是一条非常硬核的学习路径——它不教你调包不教你套壳而是要求你把AI工程化这条链路亲手走一遍从数据处理、模型训练、评估调优到部署上线、监控迭代每一步都用最底层的方式实现一次。如果你也是那种“不亲手写一遍就不踏实”的人或者你已经被各种封装好的框架养出了“只会调用、不懂原理”的焦虑这篇文章就是给你写的。我会把自己完整跑通这套从零构建流程的经验拆开讲包括每个环节的取舍逻辑、实操步骤以及那些文档里不会写的坑。1. 先把“AI工程”这件事拆明白它到底在解决什么问题1.1 AI工程不是调包也不是发论文先说一个我观察到的现象很多人以为AI工程就是“用PyTorch训练个模型”或者“用LangChain串几个大模型调用”。真不是。AI工程的核心不是模型本身而是让模型在真实业务场景里稳定、可维护、可迭代地运行。它横跨数据工程、机器学习、软件工程、DevOps四个领域任何一个环节掉链子整个系统都会崩。作为对比算法研究的关注点是模型精度指标发论文的终点是实验表格传统软件工程关注的是业务逻辑的正确性和系统的可用性而AI工程关心的是“数据怎么流动”“特征怎么对齐”“模型上线后效果衰减怎么监控”“新数据来了怎么自动重训”。这几句话说起来轻松做起来每个都是深坑。从零开始做AI工程不是让你重新发明轮子而是让你把轮子的每个零件都亲手摸一遍。比如训练一个简单的线性回归你不用sklearn的LinearRegression而是手写梯度下降部署一个模型你不用现成的serving框架而是自己用FastAPI包一层。这个过程中你会理解scaling、归一化、学习率这些参数到底在干什么理解为什么训练集准确率高但线上效果差理解一个模型从notebook到生产环境要跨过多少道坎。1.2 从零开始真正的含义每个环节都要回答“为什么”“From Scratch”这个词经常被误解。很多人以为从零开始就是不用任何第三方库连NumPy都自己实现——那是偏执。合理的理解应该是对每个核心组件你至少要亲手实现或配置一次最简版本搞清楚内部原理然后再切换到工业级工具。我见过一个学习路线图要求学习者先手写反向传播再手写Transformer的self-attention然后才允许用PyTorch。这个路线很硬核但绝大多数人会在手写反向传播那一步就放弃。真正可持续的从零开始是分层级的第一层理解理论能手推公式第二层用NumPy手写核心算法线性回归、逻辑回归、KNN、决策树第三层用成熟框架复现这些算法确认自己的实现和框架输出一致第四层用框架解决真实数据问题同时自己搭建完整的工程链路第五层把链路自动化形成可复用的平台能力这种分层的好处是你既不会被底层细节拖死也不会变成只会调API的“框架熟练工”。每一层你都知道自己在干什么、为什么这么干。1.3 这条路线适合谁三个典型人群根据我自己带过的人和网上交流的反馈这条路线最适合三类人第一类是刚入门想建立完整认知的初学者。这类人最容易被培训机构带偏上来就学深度学习结果连过拟合是什么都说不清楚更别提数据泄漏这种工程隐患。从零走一遍地基才打得牢。第二类是已经在做业务但感觉技术瓶颈明显的工程师。这类人通常会用sklearn或PyTorch跑通几个项目但换个数据集、换个业务场景就抓瞎遇到线上效果和离线评测不一致的问题也不知道怎么排查。本质上是缺乏对底层原理和工程链路的完整理解。第三类是想转型AI方向的传统软件工程师。程序员转型AI最大的优势是工程能力强但最容易缺的是数据处理和模型训练的系统方法论。从零路线刚好能把这块短板补上。2. 从零开始的完整路线我拆出来的五个主线2.1 主线一数学与编程地基——别被公式吓跑AI工程对数学的要求没有想象中那么高但也不是零。以我个人的经验按优先级排线性代数 概率统计 微积分 最优化。线性代数是深度学习的“语法”矩阵乘法、转置、特征值这些概念贯穿始终概率统计是理解损失函数和评估指标的“语感”交叉熵、极大似然、贝叶斯这些概念会反复出现。这里有一个很关键的认知数学不是为了让你推公式是为了让你能读懂开源源码里的注释、看懂实验曲线为什么长这样、能自己设计实验。比如你发现训练loss降不下去如果脑子里有“梯度消失”“学习率过大导致震荡”这些概念排查起来就有的放矢如果只是照着别人的代码抄一遍出了问题完全不知道从哪里下手。编程地基方面Python是躲不开的。除了基础语法有三件事我建议优先掌握NumPy的向量化操作、Pandas的数据清洗、以及Python的装饰器和上下文管理器。为什么专门提后两者因为写数据管道时装饰器用来做缓存和日志上下文管理器用来管理数据库连接和文件句柄这些是工程化的基础素养。2.2 主线二经典机器学习手写实现——理解算法的“手感”路线走到第二个里程碑就是手写经典算法。我的建议是至少手写这五个线性回归梯度下降版、逻辑回归、KNN、决策树ID3或C4.5简化版、KMeans。每个算法的实现都要包含完整的训练和预测流程并且要主动去和sklearn的结果做对拍。很多人觉得手写线性回归这种“老掉牙”的算法没什么意义实际上意义非常大。比如我自己当年手写线性回归时才真正搞懂了为什么特征要归一化没归一化的时候loss曲面是个狭长的碗梯度下降走得非常慢来回震荡归一化之后loss曲面变成接近圆的碗几步就收敛了。这个东西你光看理论推导是没有体感的必须亲手跑一次。对拍这一步尤其重要。你可以用随机生成的数据集分别用自己的实现和sklearn计算训练loss、测试指标然后逐项对比。如果不一致逐行排查这个过程对调试能力的锻炼价值极高。从零工程化的第一关就是学会系统性地排查“看起来差不多但数值对不上”的问题。2.3 主线三深度学习与自动微分——从手推反向传播到用框架有了经典ML的底子再进深度学习就顺很多。这一阶段的核心任务是理解反向传播。我的做法是先手写一个两层的全连接神经网络用NumPy实现前向传播、损失计算、反向传播、参数更新在iris或mnist这种小数据集上训练观察loss下降曲线。然后要做一个很重要的操作梯度检查gradient check。用数值方法近似计算梯度和你的解析梯度做对比误差在1e-6量级内才算实现正确。这一步能帮你发现90%以上的反向传播bug。很多人在学习时跳过这一步导致后面所有的训练实验都建立在错误的梯度上越调越糊涂。框架阶段PyTorch是当前最主流的选择。记住一个核心原则使用框架不等于放弃理解底层。刚开始用PyTorch时我建议手动实现一个简单的训练循环不要一上来就用Lightning这种高层封装至少要知道loss.backward()后面发生了什么。2.4 主线四LLM时代的工程新维度——提示词与RAG的工程化现在做AI工程LLM是绕不开的。这个阶段和传统ML的工程方法论有很强的延续性但新增了两个重要维度上下文工程和外部知识接入。对应到实操上就是提示词工程和RAG检索增强生成。提示词工程的工程化指的是把提示词当成代码来管。版本控制、A/B测试、回归测试一样都不能少。我自己习惯建一个prompt模板库每个模板都有版本号、评测用例、历史效果记录就像管理一个函数库一样。RAG的工程化则更像传统的信息检索系统。你要自己搭向量数据库处理文档切分设计embedding模型选型和评估方案。这里最容易犯的错误是直接用“召回率”或“精确率”这种指标评估RAG效果而忽略了端到端的生成质量。正确的做法是拆成两个层面检索模块单独评估召回率、MRR生成模块单独评估忠实度、相关性再联合评估整体效果。这套拆解方法论其实就是从经典ML里的模块化评估思想延伸过来的。2.5 主线五部署、监控与迭代——AI工程的终极试炼场模型在notebook里跑得再好不部署上线就只是demo。这一阶段要掌握的技能包括模型序列化与版本管理不只是pickle/joblib还要有模型注册表、把模型服务封装成HTTP接口FastAPI是首选、用Docker容器化、编写自动化测试包括模型输出的黄金样本测试、设计监控看板延迟、吞吐、特征漂移、预测分布漂移。有了监控数据就进入迭代闭环新数据回流、标注、重训、评估、灰度发布、全量上线。这一步看着简单做起来非常复杂涉及数据版本、特征版本、模型版本之间的对齐问题。说到这里这套路线的五个主线就完整了基础能力 → 经典算法 → 深度学习 → LLM应用 → 部署迭代。接下来我挑其中最核心的几个节点讲具体怎么实操。3. 核心实操从手写线性回归到端到端Pipeline3.1 第一步用NumPy手写线性回归理解梯度下降的每一根神经先看代码。我完整跑通过的一个版本是这样import numpy as np class LinearRegressionScratch: def __init__(self, lr0.01, n_iters1000): self.lr lr self.n_iters n_iters self.weights None self.bias None self.loss_history [] def fit(self, X, y): n_samples, n_features X.shape # 初始化参数 self.weights np.zeros(n_features) self.bias 0.0 for i in range(self.n_iters): # 前向计算预测值 y_pred np.dot(X, self.weights) self.bias # 计算损失MSE loss np.mean((y_pred - y) ** 2) self.loss_history.append(loss) # 反向计算梯度 dw (1 / n_samples) * np.dot(X.T, (y_pred - y)) db (1 / n_samples) * np.sum(y_pred - y) # 参数更新 self.weights - self.lr * dw self.bias - self.lr * db return self def predict(self, X): return np.dot(X, self.weights) self.bias def score(self, X, y): y_pred self.predict(X) u np.sum((y - y_pred) ** 2) v np.sum((y - np.mean(y)) ** 2) return 1 - u / v这段代码的核心就三步前向计算预测值、计算梯度、更新参数。看起来简单但里面藏了几个关键细节。第一梯度计算用矩阵乘法np.dot(X.T, (y_pred - y))而不是用for循环。这不仅是性能问题更是对“向量化”思维的训练。AI工程里处理的数据动辄上百万行for循环的写法在真实项目里根本跑不动。第二学习率lr的选择直接影响收敛。lr太小收敛慢lr太大loss会震荡甚至发散。我建议你在自己的实现里加一个loss_history然后绘制loss曲线亲眼看不同学习率下曲线的形态差异。我实测过用sklearn的make_regression生成数据特征数10、样本数1000的情况下lr0.01大概500轮收敛lr0.5直接发散。这个体感比看十篇理论文章都有用。第三参数初始化用全零在逻辑回归里可能会出问题但在线性回归里没问题因为MSE损失是凸函数不管从哪个点出发都能收敛到全局最优。如果你后面手写神经网络就不能用全零初始化了要改用随机初始化否则同一层的神经元会完全对称学不到不同的特征。3.2 第二步构建数据管道——真实项目里80%的工作量都在这里模型代码写完了接下来才是关键怎么把数据从原始状态变成模型能吃的样子。这一步是AI工程和算法实验最大的分水岭。我的做法是构建一个标准化的数据管道分成三步第一步数据检查与清洗。拿到一份数据别急着建模。先看有没有缺失值缺失比例多少是随机缺失还是有规律缺失有没有重复行目标变量的分布是什么形态我用Pandas写的检查函数很简单但能快速暴露问题import pandas as pd import numpy as np def inspect_data(df): report {} report[shape] df.shape report[dtypes] df.dtypes.astype(str).to_dict() report[missing] df.isnull().sum().to_dict() report[missing_ratio] (df.isnull().mean()).to_dict() report[duplicates] df.duplicated().sum() # 数值列的基本统计 num_cols df.select_dtypes(includenp.number).columns report[describe] df[num_cols].describe().to_dict() return report第二步特征工程与预处理。这一步的核心是区分不同特征类型。数值型特征通常需要归一化或标准化类别型特征需要编码one-hot或label encoding时间型特征要拆成年、月、日、星期等周期特征还有缺失值填充策略的选择。这里有一个我踩过的大坑缩放器必须在训练集上fit不能在全部数据上fit。假设你有train和test两份数据如果你在合并后的全部数据上做标准化然后切分test的信息就泄露到了train的分布里。这样测出来的指标会虚高上线后立刻现原形。第三步数据版本管理。数据是会变的。今天用这个特征集明天加了两个特征后天后端修复了一个埋点bug导致数据口径变了。如果不做数据版本管理你的模型复现工作就是一个灾难。我的做法很朴素每个数据集文件命名带上日期和版本号同时在实验记录里记录每个实验使用了哪个数据版本、哪个特征列表、哪个模型代码commit。可以用MLflow管理但一开始手动管理也好过完全不管理。3.3 第三步模型评估与过拟合诊断——不只盯着准确率模型训练完成后的第一件事不是高兴而是怀疑这个结果是真实可靠的还是过拟合了还是发生了数据泄漏我总结了一套评估流程先看学习曲线就是训练loss和验证loss随训练轮数的变化。如果训练loss持续下降但验证loss先降后升就是典型的过拟合如果两个loss都降不下去可能是模型容量不足或特征质量差如果训练loss就降不下去先检查梯度是否正确再看学习率。再看误差分布不要只看平均指标。用残差图检查预测误差是否是均值为0的正态分布如果残差有明显模式比如在某个取值区间系统性偏高或偏低说明模型还有没捕捉到的非线性结构。最后做交叉验证但要注意数据的时序性。如果是时间序列数据不能用普通的K-fold随机切分因为未来数据不能用来训练。正确的做法是TimeSeriesSplit按时间顺序扩展窗口保证训练集永远在测试集之前。我自己很喜欢画一张“预测vs实际”的散点图如果点均匀分布在对角线附近说明模型拟合良好如果形成明显的弯曲形态说明还有非线性关系没学到。这种图比堆一堆指标更直观、更有诊断价值。3.4 第四步模型服务化部署——让模型从.ipynb走向生产模型在notebook里是“活”的要部署成别人能调用的服务需要过五关斩六将。我自己的最小可用方案是这样的第一关把模型和预处理逻辑打包成一个类确保load_model之后能直接用。这里的关键原则是预处理逻辑和模型必须绑定在一起不能散落在各处。我写过一个封装类把标准化器、模型、后处理逻辑都塞进去对外只暴露一个predict方法。第二关用FastAPI写一个极简的HTTP服务from fastapi import FastAPI from pydantic import BaseModel import joblib import numpy as np app FastAPI() # 加载模型和预处理器 model joblib.load(model.joblib) scaler joblib.load(scaler.joblib) class PredictRequest(BaseModel): features: list[float] class PredictResponse(BaseModel): prediction: float probability: float | None None app.post(/predict, response_modelPredictResponse) def predict(req: PredictRequest): # 输入校验维度要和训练时一致 X np.array(req.features).reshape(1, -1) X_scaled scaler.transform(X) pred model.predict(X_scaled)[0] return PredictResponse(predictionfloat(pred))第三关Docker化。这里有一个非常容易踩的坑镜像构建时不要把训练代码和训练数据打进去镜像只需要模型文件和服务代码。我见过有人把几个G的训练数据塞进镜像里导致镜像构建失败、启动巨慢。正确做法是模型文件挂载或从模型仓库拉取。还有一个小坑FastAPI的float类型默认是float64而你训练时用的可能是float32矩阵运算时类型不匹配会静默出bug。建议在请求入口处显式做类型转换。3.5 第五步监控与迭代——模型上线只是开始模型上线那一刻真正的AI工程才刚开始。第一个要监控的是数据漂移。就是模型上线前和上线后输入特征的分布是否发生了变化。比如你训练模型时用户的年龄段分布是25-35为主上线三个月后变成了18-25为主模型的效果就可能已经不可靠了。监控方法很直接定期用统计检验如KS检验、PSI对比线上特征分布和训练时特征分布的差异超过阈值就报警。第二个要监控的是预测分布漂移。即使输入特征没变但模型预测结果的分布如果发生明显偏移说明业务环境或用户行为变了。比如一个风控模型线上预测的违约概率均值从0.2涨到了0.4这不是模型自己出的问题而是外部环境变了这时要人工介入判断模型是否仍适用。第三个要设计的是模型重训与更新机制。我的建议是设置一个明确的重训触发条件。可以是定期每周/每月也可以是事件驱动监控指标触发报警最好是两者的结合。重训后不能直接上线要先在离线数据集上评估再走灰度发布流程把新模型和老模型的线上效果做对比确认没有回退后再全量切换。这一套走下来你会发现AI工程的核心不再是“训练一个好模型”而是“构建一个能让模型持续产生价值的系统”。4. 踩坑实录从零开始最容易在哪几个地方翻车4.1 数据泄漏最隐蔽、最致命的错误数据泄漏是AI工程里最可怕的bug因为它不会报错模型指标会很高上线后效果却崩盘。常见的泄漏形式有这么几种一是预处理泄漏前面提到的在全部数据上做标准化再切分就是典型。二是时间泄漏用未来的数据预测过去。三是目标泄漏特征里包含了和标签直接相关的信息。比如预测用户是否会逾期结果特征列表里有一个“是否逾期过”的字段这模型离线分数会爆表上线后这个字段根本拿不到。排查数据泄漏的方法很简单检查特征和标签的时间先后关系。所有特征的时间戳必须在标签产生时间之前否则一律视为泄漏。这个检查要写成自动化规则每次做特征工程时都跑一遍。4.2 训练与推理不一致换环境就翻车训练时和推理时用的预处理逻辑不一致是最让人抓狂的bug。比如训练时你对文本做了正则清洗推理服务里忘了训练时缺失值填充用的是训练集的中位数推理时却用了0。这种问题模型不会报错但效果就是不对。我的解决办法是把预处理逻辑封装成唯一的数据变换模块训练和推理统一从那里调用并在测试集上验证“预处理→模型”的完整流程输出和预期一致。需要特别注意这种验证的测试数据要覆盖边界情况空字符串怎么办全NaN的行怎么办特征维度不对怎么报错4.3 评估指标选错对业务目标视而不见分类问题无脑用accuracy是新手最容易犯的错。在类别不平衡的场景下比如欺诈检测正样本比例1%一个把所有样本都预测为负类的模型也有99%的准确率。选择指标首先要看业务目标。欺诈检测的评估重点是查准率precision和召回率recall因为漏掉一笔欺诈的代价远大于误报一笔推荐系统的评估要看排序质量NDCG、MRR这些更合适回归问题如果用MSE可能被异常值主导有时MAE或Huber损失更贴近业务需求。正确做法是先定义业务损失函数倒推最合适的评估指标再决定用什么优化目标。4.4 依赖管理混乱另一台机器上跑不起来从零开始做工程一定会遇到环境问题本地能跑服务器上一堆报错今天能跑下周就跑不了。这些问题的根源就是依赖没有锁版本。我的做法是用requirements.txt锁直接依赖用pip freeze生成全量锁定版本同时提供Dockerfile保证环境完全一致。如果你用Conda也要导出environment.yml锁定版本。不要把“我这本地能跑”当成借口环境可复现是工程化的底线。4.5 常见问题速查表问题现象可能原因排查方法训练loss高怎么调都降不下去特征未缩放、学习率过大或过小、梯度实现错误绘制loss曲线检查特征分布做梯度检查训练loss低验证loss高过拟合模型容量过大降低模型复杂度增加正则化做交叉验证离线指标高线上效果差数据泄漏、训练推理不一致、分布漂移做泄漏排查统一预处理逻辑监控特征分布服务响应慢吞吐上不去模型推理无批处理、特征处理冗余用batch推理对预处理做缓存模型上线一周后效果下滑数据漂移、业务环境变化监控特征分布和预测分布触发重训5. 工具链选型与工程化习惯哪些工具值得投资5.1 环境与依赖管理Python项目我现在的标准配置是用conda管理Python版本用venv加pip管理项目环境。关键是环境必须可复现用一个environment.yml记录所有依赖而不是临时想起来一个装一个。装依赖时有个习惯值得养成不要直接装最新版先看项目需要的版本范围用pip install numpy1.21,1.25这种形式锁定范围避免大版本升级带来的隐性API变动。5.2 实验记录与版本管理我强烈建议从第一个实验开始就用MLflow管理。MLflow能跟踪四样东西实验参数超参数、实验指标loss、accuracy、模型产物artifact、以及代码版本。它的手写版替代方案是用JSON文件记录每次实验的配置和结果用Git commit哈希标记代码版本。手动方案的好处是零依赖但不方便检索和可视化数据多了之后还是得切到MLflow。关于Git本身我有个特殊建议不要在notebook上直接跑Git。notebook是JSON格式每次运行都会改变输出cell的“脏数据”Git diff根本没法看。正确做法是notebook只用来做探索性分析正式代码要抽成.py文件并纳入版本管理。我自己的习惯是notebook目录和正式代码目录严格分离。5.3 任务编排一个真实的AI项目不会只有一个训练脚本它有数据预处理任务、特征工程任务、训练任务、评估任务、部署任务。手动一个个跑非常容易出错。我推荐用Makefile或snakemake做最基本的任务编排把这些步骤串起来make prepare、make train、make evaluate、make serve一键执行。等流程变复杂了再考虑Airflow或Prefect这种专业调度工具。这个习惯的收益在一开始可能看不出来但当你要重跑一个三周前做的实验时一个命令能把所有步骤串行执行完你就知道有多香了。6. 最后的几点体会与一个小技巧我完整跑完这套“from scratch”路线之后最大的体会是AI工程的能力不是靠看教程看出来的是靠自己踩坑踩出来的。你亲手把线性回归的梯度下降实现一遍、把FastAPI服务和Docker容器搭一遍、把监控系统碰到一次特征漂移修一遍这些经历积累起来的东西才是真正能迁移到任何AI项目里的底层能力。最后分享一个我一直在用的实用技巧每一类任务都建立一个最小模板仓库。比如我维护了三个模板数据处理模板、模型训练模板、服务部署模板。新项目启动时直接复制对应模板再修改不重复踩坑。这个习惯帮我省下了大量重复造轮子的时间——特别是部署模板每次更新之后后面所有项目的上线速度都能快不少。如果你想做AI工程但不知道从哪里开始我的建议很简单选一个你最熟悉的业务场景用本文的路线把它从零完整走一遍。不要贪多一个场景走通胜过十门课程。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进