
做AI工程这几年我最大的感受是很多人学完机器学习课程、跑通几个Notebook之后一进入真实项目就懵了。模型在验证集上准确率挺高可一上线就崩训练环境好不容易配好隔壁同事一跑代码就各种版本冲突调参调了三天最后发现是数据源的bug。这些都不是算法问题而是工程问题。所谓“AI engineering from scratch”说的就是从零开始把一个模型从“能跑”变成“能用、好用、能长期维护”的全链路能力。它不是某个算法课的进阶也不是DevOps的简单套用而是把数据、模型、训练、部署、监控、迭代这一整套流程当成一个系统工程来设计。这篇内容就是我从零搭建过多个AI项目后沉淀下来的一套实战路径。适合那些已经会写Python、了解基础机器学习概念但还没完整做过一个端到端AI项目的同学也适合在小团队里要自己扛起模型落地全流程的工程师。我会把整个过程中最关键的设计决策、踩过的坑、以及每一步为什么这么做讲清楚尽量少讲空泛的理论多给能直接照着做的方案。1. 项目设计的第一步不是模型而是“问题重定义”很多从零开始的AI项目败就败在第一步太兴奋先选了一个Spare模型然后找数据再然后开始训练。正确的顺序应该是反过来的——先搞清楚要解决的问题到底是什么形态再决定要不要用AI、用什么粒度去做。1.1 把业务问题翻译成机器学习问题我习惯先把需求拆成四层业务目标比如“降低客服人工成本”或“提高搜索点击率”决策行为帮谁做什么决策比如“给用户推荐一篇文档”或“判断一个工单该转给哪个组”预测目标需要什么输入、输出什么分类、回归、排序、生成成功指标不是准确率而是业务指标比如节省了多少人力、留存提升了多少这个翻译过程不投任何代码但比代码更重要。我见过一个团队花了两个月做一个“智能分诊”模型最后发现大部分工单只需要简单的关键词规则就能处理模型带来的增量不到3%。如果事先把问题定义清楚就会算出投入产出比选择先上规则系统把AI放在最复杂的长尾问题上。1.2 什么时候真的需要“从零训练”现在预训练模型和现成API这么多“从零”有两个层面的含义从零搭建训练管线用公开的底座模型训练自己的下游头从零实现网络结构自己写Transformer、CNN这些算子对绝大多数项目来说第二种“从零”没有必要。除非你是做学术研究或者要在特殊硬件上部署自研结构否则直接用PyTorch或主流库搭好的架构把精力放在数据和管理上性价比高得多。真正的“from scratch”应该体现在你有能力控制整个管线而不是能手写反向传播。2. 技术栈选型与工程环境搭建AI工程的核心矛盾是实验阶段需要快速迭代生产阶段需要稳定可控。技术栈选型必须在两者之间找平衡。2.1 核心框架PyTorch是默认选择除非你维护的是TF老项目或者被某个云平台深度绑定否则我建议新项目直接上PyTorch。理由很实际动态图对调试友好配合print或debugger能直观看到中间张量生态最活跃HuggingFace、Lightning、TorchServe都是原生支持社区资料多遇到问题搜解决方案最快但要注意PyTorch版本和CUDA版本的匹配是个典型坑。我建议一个项目固定一个虚拟环境用conda或python -m venv把requirements.txt和pytorch版本锁死。不要追求最新版稳定优先。我自己踩过一次A卡机器上装了默认最新CUDA 12.x的PyTorch结果另一台旧机器的GPU是CUDA 11.8两边同步代码后跑不起来花了半天解决版本冲突。2.2 训练管线的管理工具用Lightning还是裸PyTorch如果项目规模不大裸PyTorch足够但你会手写training loop、checkpoint、日志这些代码很容易出错且难以复用。PyTorch Lightning把这些模板化管理起来代码量减少而且训练、验证、测试流程清晰。我的建议是超过300行训练代码就上Lightning否则裸写也行。不过Lightning有个反直觉的地方——它包装太多出了问题你不好定位。所以debug阶段我通常还是用裸PyTorch写一个小脚本跑通了一个batch再迁移到Lightning框架里跑完整训练。2.3 数据存储与版本管理AI工程的隐形工作量一大半在数据。数据文件在本地、测试环境和生产环境之间传来传去很容易出现“模型训练时用的数据和评估时用的是同一批但顺序不同”这种诡异现象。数据版本管理推荐两种方案小数据GB级直接用Git LFS 固定的目录结构每个数据文件标注日期和版本大数据几十GB以上用DVC或WB Artifacts把数据的哈希和元数据记录下来训练实验时能准确复现最简单的起步方案是给数据目录加一个data_version.json包含每个文件的md5值和更新时间训练脚本加载前先校验。这个习惯能省掉大量排查时间。2.4 实验跟踪从Excel到WB实验记录早期可以用Excel但一旦参数组合超过几十组就记不住了。我推荐用Weights BiasesWB或MLflow关键是记录以下信息代码git commit id确保可以回溯到确切代码数据版本md5或DVC哈希超参数dict完整值环境包版本pip freeze的输出训练日志中的loss曲线、验证集指标每次实验结束把这些信息一键保存。没有实验跟踪你调的参赛就没有历史过两周回来根本分不清哪个配置最好。3. 数据处理与特征工程模型的起点模型再花哨数据垃圾输出必垃圾。数据处理不仅耗时而且直接决定模型性能上限。3.1 数据采集明确Y标签的来源监督学习必须有标签。从零开始的项目最容易忽略的是标签怎么来、是否可靠、是否有偏。常见来源有几种历史日志里的行为指标比如点击/购买人工标注用标注平台或自建简单脚本规则自动生成、人工抽检我强烈建议先做小样本标注比如500条分析一下标签分布。如果类别极度不均衡比如正样本只有1%那就要决定是过采样、欠采样还是换用异常检测框架。这个决定要在训练前做而不是等模型出来再看。3.2 清洗与预处理清洗的坑容易被忽略。我总结过五个必查项缺失值是随机缺失还是非随机需要按列统计缺失率再决定删除还是填充重复样本完全重复容易看到但“同样用户不同时间”的行为样本可能不能直接去重需要根据业务逻辑判断异常值用分位数、Z-score或箱线图检测尤其关注业务上不可能出现的值比如负数的库存、未来时间戳文本数据编码统一成UTF-8Emoji、全角半角符号需要注意日期时间时区问题很隐蔽存储用UTC或带时区偏移避免因本地时区导致的数据错位3.3 特征构建先简单后复杂不要一上来就搞上百个特征。先把基线做出来然后逐步加特征每次加一批都验证是否真的提升验证集效果。优先考虑业务上有明确意义的特征统计类历史均值、方差、频次、最近一次时间间隔文本类TF-IDF、预训练向量bert/RoBERTa-embedding降维时间类星期几、小时数、节假日等特征工程不是越复杂越好关键是要与问题结构匹配。我做过一个推荐项目加了交叉特征后线上A/B测试反而下降因为交叉特征在训练集过拟合了冷门组合。4. 模型训练与调优的实操流程训练阶段需要一套可复制的流水线。4.1 数据集划分训练/验证/测试的黄金标准划分时要注意“随机”不是最佳选择。对于有用户ID或时间序列的数据需要按用户或时间分组避免数据泄漏。比如用户A的信息出现在训练集用户A的另一条又在测试集模型就会“作弊”测试指标虚高。推荐三种划分方式按场景选择时间序列按时间切分前80%训练后20%测试用户行为按用户ID分桶确保同一用户的记录不跨集普通样本分层抽样保持标签比例近似划分完以后验证集和测试集都要冻结不允许根据测试集结果调参。测试集只在最终评估时用一次。4.2 损失函数与评估指标的选择分类问题要看业务容忍哪种错误。如果假阳性代价高比如误判风险事件要多关注精准率假阴性代价高比如漏检疾病就多关注召回率。F1只是粗略平衡更推荐使用PR曲线下面积或自定义带权重的损失。训练时损失函数不一定和评估指标完全一致。比如排序问题评估用NDCG但训练常用Listwise损失或Pointwise的BCE合理设计即可。4.3 训练参数的经验基准以下是一套我用下来比较稳的起始参数适合中小型模型参数建议起始值说明Batch size32 / 64显存不足可以梯度累积学习率3e-4AdamW太大容易发散太小收敛慢权重衰减0.01对预训练模型微调有效Epochs3-10用早停法patience3Warmup总步数的5%-10%避免初始震荡梯度裁剪max_norm1.0防止梯度爆炸早停法很重要直接监控验证集loss连续3个epoch不降就停。自己训练过千次就会发现大多数模型在3到5个epoch内收敛拖着训练只会过拟合。4.4 从基线模型开始永远先做一个简单基线最多是线性模型或小决策树或者直接是规则。基线的作用不是最终方案而是告诉你AI模型带来的增量是否值得复杂度。如果简单模型已经达90%的F1复杂模型只涨0.5%但推理时间慢三倍那要重新评估价值。5. 模型部署与线上服务化训练完模型只是开始部署才是工程化的重头戏。5.1 模型保存与服务方式选择不同场景选择不同部署方式单模型调用低频使用FastAPI包一个简单的预测接口加载模型到内存每次请求做预处理推理后处理多模型并存/版本灰度使用TorchServe或KServe自带版本管理和指标输出端侧部署转成ONNX、TensorRT或TFLite在边缘设备上跑最起始建议用FastAPI因为灵活、调试方便、文档自动生成。一个基础示例from fastapi import FastAPI, Request from pydantic import BaseModel app FastAPI() model None class PredictRequest(BaseModel): text: str app.on_event(startup) def load_model(): global model model load_your_model() app.post(/predict) def predict(req: PredictRequest): features preprocess(req.text) result model.predict(features) return {result: result}这种方案足够覆盖内部工具和中小流量场景。如果后续流量增加可以加Redis缓存、改成异步处理或加负载均衡。5.2 推理性能优化模型上线前必须做性能测试。关键指标有两个P99时延99%的请求在多少毫秒内完成QPS每秒能处理的请求数常见的优化手段将不需要梯度的模型设为model.eval()并在torch.no_grad()下推理Batch推理把多个请求拼成一个batch在GPU上并行吞吐能提升数倍半精度FP16/INT8精度损失小但显存和速度改善明显量化注意极端数值下可能掉点5.3 上线前的测试清单我每次上线前都会过一遍以下检查输入非法值空字符串、缺失特征、类型不对不会导致500预测结果与训练时的逻辑一致离线/在线相同样本输出相同模型文件是否通过hash校验避免加载到旧版本超时与重试机制上游超时不能拖垮模型服务优雅关停K8s滚动更新时旧进程处理完当前请求再退出6. 监控与持续迭代部署完成不等于结束监控和迭代是AI工程的另一个半场。6.1 监控什么系统指标耗时、内存、GPU利用率、错误率模型指标请求量、输入分布feature shift、预测分布、置信度分布业务指标点击率、转化率、留存等特征漂移是AI系统特有的风险。比如训练时用户年龄特征是0-80上线后出现130说明数据源出了问题。可以定期计算特征的均值、方差或分位数与训练集做对比超过阈值就告警。6.2 A/B测试与线上评估不要用离线指标直接拍板上线。做一个分流实验将流量按比例分配到新旧模型观察业务指标。样本量不够时先用影子模式运行新模型记录预测结果但不影响线上决策离线对比一致性。6.3 数据回流与再训练周期性利用新反馈数据重新训练模型两周或一个月一次按业务节奏而定。把每个月的样本导出为固定格式的数据集重新走训练、评估、部署流程。再训练前一定要检查新数据分布是否发生变化否则模型只会在原地打转。7. 常见问题与排查实录分享几个我实际遇到过的坑以及排查思路。7.1 训练loss下降但验证指标震荡多半是训练数据与验证数据分布不一致或者验证集太小。先检查验证集样本量必须足够大且分层随机。再看数据泄漏看验证集是否包含了训练集的重复或相关样本。最后考虑调低学习率、增加Dropout或正则。7.2 GPU显存不足降低batch size增加梯度累积步数使用混合精度训练AMP减小输入序列长度或图像分辨率检查是否有Pytorch缓存没释放torch.cuda.empty_cache()严重时只能换更大显存或分布式训练7.3 模型服务上线后比离线差很多常见的三类原因线上特征值缺失或预处理不一致离线测试时用了model.eval()但线上误用了model.train()数据漂移导致的分布变化排查方法也很直接把线上真实请求记录下来放到离线环境跑一遍对比。如果差异大说明预处理或环境有bug逐段检查。7.4 依赖环境污染Python环境问题是最大的隐性成本。建议每个项目都用独立的conda环境并且用poetry或uv管理依赖锁定精确版本。尽量避免在base环境里装包。踩过最惨的一次是升级了NumPy导致一个旧模型在推理时出现完全不同的结果排查了两天才找到是版本问题。7.5 训练数据集大但加载慢Dataloader的num_workers设置为CPU核心数的一半左右启用pin_memoryTrue让数据对拷到GPU时更快数据存储用TFRecord或HDF5分片减少小文件随机读取。8. 我个人的几个体会最后分享几个自己反复验证过的经验。第一先跑通最小闭环再谈优化。从零开始做一个AI项目第一步不是追求精度而是把一个样本从原始数据走到预测结果的流程跑通。哪怕预测结果很差但只要链路是完整的后续所有优化都有抓手。很多项目烂尾就是因为一开始就想同时解决数据、模型、部署所有问题。第二工程文档比代码本身更重要。这里说的不是写冗长的技术文档而是在项目根目录放一个README写清楚数据从哪来、怎么处理、训练命令是什么、模型怎么部署、版本怎么迭代。团队协作时这份文档能避免大量“你昨天改了啥”的对话。第三自动化是持续交付的保证。用CI/CD把训练、评估、部署步骤自动化至少要做到一键训练、一键部署。哪怕是脚本也好。AI工程最忌讳手工操作手工操作一定会出错。第四保持简单直到有证据表明需要更复杂。模型架构、特征工程、服务架构都是这样。用一个简单方案跑一段时间收集数据再决定是否升级。很多团队从第一天就引入了微服务、K8s、特征平台结果做了一年还在搞基础设施实际的模型根本没法发布。从零开始做AI工程本质是学会用最小可行的手段把模型的整个生命周期管起来。所以你不一定需要最先进的算法但需要最稳的工程习惯。