1. 这个项目到底在做什么
1.1 从零开始学的不是调包
“ai-engineering-from-scratch”这个项目标题,乍听起来像某个课程的名字,但实际做下来的体感完全不同。它解决的并不是“怎么调用现成模型接口”的问题,而是从一个完全没有AI工程背景的状态,一步步把AI项目从数据准备、模型训练、评估调优到部署上线完整地跑通。核心关键词是“from scratch”,也就是不依赖现成的完整方案、不跳过底层细节,亲手搭建整个流程。
我最初接手这类项目时,以为主要任务就是训练一个模型。真正做了几轮之后才发现,训练只占整个工作量的三成左右,剩余的大头全在数据清洗、特征工程、实验管理、模型部署以及后续的监控迭代上。这个项目之所以值得参考,恰恰是因为它把这些容易被忽略的“工程环节”老老实实补全了,读者跟着走一遍,就能建立起对AI项目全生命周期的认知。
这个内容比较适合三类人:一是刚入门机器学习、想搞清楚模型到底是怎么从原始数据变成线上服务的同学;二是在传统软件开发领域想转型AI方向、需要一套完整实操路径的工程师;三是已经在跑模型但总是在部署环节出问题的实践者。无论哪类读者,跟着从零开始走一遍完整流程,远比碎片化地学某个算法或框架更有价值。
1.2 完整图谱:AI工程化五层结构
我习惯把整个AI工程化体系拆成五层,这样在设计学习路径和实战项目时就不会迷失方向:
- 数据层:数据采集、清洗、标注、特征工程、数据版本管理
- 算法层:模型选型、损失函数设计、训练策略、超参数调整
- 训练层:实验追踪、分布式训练、资源调度、GPU利用率优化
- 部署层:模型序列化、推理服务封装、接口设计、性能压测
- 运维层:模型监控、数据漂移检测、版本迭代、回滚机制
很多初学者把注意力全放在算法层,尤其喜欢研究各式各样最新的模型结构,但实际上企业里真正影响项目成败的往往是数据层和运维层。这个项目用“from scratch”的方式走一遍这五层,本质上就是在给读者补上这些关键的能力拼图。
2. 核心基础:哪些值得花时间死磕
2.1 数学与Python,先打地基
先说结论:做AI工程化并不需要成为数学专家,但三个方向的数学基础必须过关——线性代数、概率论和微积分。这三个方向对应的实际场景分别是:张量运算与矩阵变换、不确定性建模与损失函数推导、梯度下降与反向传播的理解。
很多人会问,难道不是会调框架就行吗?我的体会是,如果你只满足于跑通示例代码,那确实不需要太多数学。但一旦遇到模型训练不收敛、loss震荡、梯度爆炸这类问题,数学功底就是排查问题的核心武器。比如当年我调试一个文本分类模型时,发现训练到一半acc上不去,后来检查发现是softmax的temperature参数设置不合理,导致logits尺度过大,Softmax输出接近one-hot,梯度变得极小——这就是概率论基础知识的典型应用场景。
Python基础同样重要,但重点不只是语法,而是面向数据科学场景的Python编程习惯:熟练使用NumPy做向量化运算、用Pandas做数据清洗、用Matplotlib/Seaborn做可视化分析,以及掌握Python的装饰器、生成器、上下文管理器等特性——这些在写训练脚本和推理服务时会大量用到。
2.2 机器学习核心原理,训练的关键
我建议别一上来就冲深度学习,而是先把经典机器学习的核心原理吃透。具体来说,需要掌握:线性回归与逻辑回归的推导、决策树与集成学习(尤其是随机森林和Gradient Boosting)、SVM的基本思想、K-Means/PCA等无监督方法的原理和适用场景。
为什么经典ML这么重要?因为深度学习本质上是在这些基础概念之上发展起来的。逻辑回归的损失函数和神经网络输出层的设计一脉相承;集成学习的思路在深度学习里对应着模型集成和Bagging策略;PCA的思想后来演变成了各种表征学习方法。更重要的是,真实业务场景中大量问题用经典方法就能解决得很好,并不需要动用大模型。
在“from scratch”的实践过程中,我会建议你手写一遍线性回归和逻辑回归的实现,不调用sklearn,用NumPy一步步实现梯度下降。这个练习能帮你彻底搞懂模型训练的本质逻辑,后面切换到深度学习框架时会顺畅很多。
2.3 深度学习与框架选型
当基础打牢之后,就可以进入深度学习的部分了。此时的关注点应该放在:神经网络的训练机制(前向传播、反向传播、优化器选择)、常见网络结构(CNN、RNN、Transformer)、以及不同任务类型的建模思路(分类、回归、序列标注、生成)。
框架选型这块,我个人的建议是分阶段来看:
| 阶段 | 推荐框架 | 原因 |
|---|---|---|
| 初学阶段 | PyTorch | 动态图机制更直观,调试方便,社区资源最丰富 |
| 工业落地 | PyTorch为主 | 生态完善,从训练到部署的工具链最成熟 |
| 特定场景 | TensorFlow | 部分存量系统仍在使用,TFLite在移动端有一定优势 |
| 快速原型 | Keras | 已经集成到TensorFlow中,适合快速验证想法 |
这里提一个很容易踩的坑:不要同时在多个框架之间反复横跳。选定一个主攻框架,至少认认真真做三到五个完整项目,再考虑是否学习其他框架。我当时就是PyTorch和TensorFlow来回切换,结果两边都不深入,实验代码风格混乱,出了问题都不知道是该查框架文档还是查自己的代码逻辑。
2.4 工程化:这才是“工程”二字的分量
如果说算法是AI项目的大脑,那工程化能力就是让这个大脑真正运转起来的骨骼和肌肉。在“from scratch”的项目实践中,工程化能力具体体现在几个方面:
- 代码组织能力:训练脚本、数据处理、模型定义、评估逻辑如何分模块,如何做到可复用和可测试
- 版本管理能力:不只代码要版本管理,数据和模型同样需要版本管理,否则复现实验会变成一场噩梦
- 容器化能力:用Docker封装环境和依赖,保证本地训练和线上部署环境一致
- 编排调度能力:训练任务、数据流水线、模型评测任务如何通过工作流工具自动串联执行
- 监控告警能力:模型上线后,如何判断效果是否在衰减、数据分布是否发生变化
这几项能力都不是算法理论本身,却是决定AI项目能否真正落地、是否能持续产生价值的关键。我在后面的实操章节会展开讲具体怎么做。
3. 实操路径:从环境搭建到模型上线的完整流程
3.1 环境准备:本地GPU vs 云GPU
首先解决算力问题。做深度学习训练没有GPU基本寸步难行,但并不是所有人都需要立刻采购顶级硬件。我建议分层选择:
- 学习调试阶段:一张RTX 3060或4060(12GB显存以上)在本地就足够跑大部分经典模型和小规模数据集
- 中等规模训练:租用云GPU服务器(按小时计费,单卡A100或V100),适合跑需要更大显存和更多算力的实验
- 生产环境训练:企业内部通常使用GPU集群管理平台,通过容器化方式提交训练任务,实现算力资源共享
这里分享一个实操细节:本地环境显存不足时,可以先用小batch size快速调试代码逻辑,确认能跑通之后再切到云环境用大batch size正式训练。这样可以避免云环境按小时计费却把时间浪费在debug上的尴尬。
环境搭建具体包括:安装Python虚拟环境(推荐Miniconda)、安装CUDA和cuDNN(注意与PyTorch/TensorFlow版本的兼容性)、安装核心依赖库。我通常在conda环境里用requirements.txt锁定依赖版本,训练代码用export PYTHONPATH=$PWD来管理模块导入路径。
3.2 数据工程:真实项目里60%的时间都花在这
很多人以为“from scratch”项目的重头戏是算法实现,实际上数据工程才是最耗时、最考验功力的环节。一个典型的AI数据集处理流程包括:数据收集、格式统一、缺失值处理、异常值检测、类别平衡处理、特征标准化、数据切分。
我处理过一个真实场景:原始数据来自多个业务渠道,格式完全不统一,有的字段是JSON,有的是嵌套的XML,还有的直接就是无结构的日志文本。当时的处理思路是先写一个数据标准化脚本,把所有数据统一转成Parquet格式,然后针对每个字段定义清洗规则,再逐条验证清洗效果。
数据质量验证特别重要。我在实际操作中会写一套简单的统计脚本,包括:每列的缺失率、均值/标准差、取值分布直方图、类别值数量。把这些跑完,基本就能对数据质量心里有数。我的经验是,花三天时间清洗数据,往往比三天时间调模型参数提升效果更明显。
3.3 训练:从基线到实验追踪
训练过程是整个项目中充满实验性和迭代性的环节。我习惯按这样的顺序推进:
- 第一步,建立基线(Baseline):用一个相对简单的模型配合默认参数,快速跑通整个训练流程,目的是验证数据管线、训练代码、评估流程没有bug
- 第二步,优化数据与特征:在基线模型之上,通过特征组合、数据增强、类别重加权等方式观察效果变化
- 第三步,升级模型结构:在数据和特征相对稳定后,再切换到更复杂的模型结构,合理比较不同模型的收益
- 第四步,调参与正则化:最后阶段关注学习率调度、Dropout比例、Weight Decay等细节
实验追踪是训练环节中最容易被新手忽略的部分。我强烈建议从第一个实验开始就用实验管理工具,比如MLflow或Weights & Biases。手工记录实验参数和结果会导致灾难性的混乱,因为调参过程中参数组合实在太多,靠记性很快就会搞混哪些配置对应哪个结果。
具体操作上,每个实验至少记录:数据版本、代码commit号、模型配置、训练超参数、训练时间、最终评估指标、loss曲线。这样即使过了几个月,也能完整复现当时的实验结果。
3.4 评估与调优:不要只看accuracy
很多初学者会用准确率(accuracy)作为唯一评估标准,这是AI工程中最隐蔽的误区。准确率在类别不平衡场景下会极具欺骗性——比如一个二分类任务中90%的样本是负样本,模型全部预测为负就能拿到90%的准确率,但这个模型在实际场景中毫无用处。
我建议针对不同任务类型选择合适的评估指标:
| 任务类型 | 核心指标 | 辅助指标 |
|---|---|---|
| 二分类 | AUC、F1-Score | Precision、Recall、Confusion Matrix |
| 多分类 | Macro-F1、Micro-F1 | 各类别的Precision/Recall |
| 回归问题 | MAE、RMSE | R^2、MAPE |
| 排序场景 | NDCG、MRR | HitRate、Recall@K |
| 生成任务 | BLEU、ROUGE | 人工评估、嵌入相似度 |
调优阶段有一个很重要的原则:一次只改一个变量。如果同时改了学习率、网络结构、数据增强方式,即使效果变好了,你也不知道是哪个改动起了作用。规范的实验流程应该是在基线稳定的前提下,逐项更改变量并记录效果。
3.5 部署:模型文件与推理服务的转换
模型训练完成后,部署是最后一道关卡。常见的部署方式有几种:
- 在线推理服务:通过RESTful API或gRPC暴露模型接口,实时响应客户端请求
- 离线批量推理:对海量数据进行定时批处理,生成预测结果写入数据库或文件
- 边缘端部署:将模型压缩转换(如ONNX、TensorRT、量化),部署到手机或IoT设备上
从训练产物到部署服务,中间要过的技术关卡不少。首先是模型序列化问题,PyTorch训练好的state_dict需要和模型结构定义一起打包成完整的推理文件(推荐TorchScript或ONNX格式)。其次是推理服务的性能优化,包括:输入批处理(动态batching)、用GPU/CPU的资源配置、异步处理框架。
我在部署一个文本分类模型时遇到了一个始料未及的问题:本地测试时单次推理延迟只有20ms,但部署到线上后延迟飙升到200ms以上。排查后发现是本地的GPU推理和线上CPU推理的性能差距,加上线上服务没有做输入批处理优化,大量请求串行处理导致效率极低。最终通过引入动态批处理机制,把线上延迟降到了40ms左右。
这个经验值得反复强调:部署环境的性能特征和开发环境完全不同,模型上线前一定要在目标环境的真实负载下做压测。
4. 真实项目里的常见问题与排查实录
4.1 数据问题:模型不收敛怎么办
模型训练不收敛是最常见的AI工程问题,但90%的情况根源不在模型结构,而在数据。按“从数据到模型”的排查顺序,我总结了一套自己的排查清单:
- 检查数据标签是否准确,有没有标注错误或标签冲突的样本
- 检查特征是否有全零列、无穷值、极端的量纲差异
- 检查数据切分是否泄露,比如训练集和验证集之间存在重叠或时序穿越
- 检查是否做了正确的数据归一化(标准化、Min-Max、RobustScaler各有适用场景)
- 检查类别不平衡是否严重到模型直接坍塌到多数类
有一次我在做多分类任务时,loss在训练前期快速下降,但很快进入平台期不再变化。通过逐层输出了中间激活值后,发现特征向量的方差过大,导致网络深层激活值普遍进入饱和区。解决方式是在特征输入层之前增加BatchNorm层,同时调整了初始化方式,问题就解决了。
4.2 过拟合实战排查
训练集指标好、验证集指标差,这是过拟合的典型信号。常用的应对手段包括:
- 增加训练数据量或做数据增强(图像领域的旋转/裁剪/色彩扰动,文本领域的同义词替换/回译)
- 添加正则化项(L1/L2正则化、Dropout、Label Smoothing)
- 简化模型结构或减小模型容量
- 使用早停(Early Stopping)机制,监控验证集指标在连续若干epoch不提升时停止训练
我的个人习惯是同时采用多种手段,但每次先验证单一手段的有效性。比如先单独加Dropout观察效果,再考虑是否加入数据增强。一次性组合太多正则化策略会把模型压得太保守,导致欠拟合。
4.3 部署环节的坑
部署环节同样有不少容易被忽视的坑,我整理了几个高频出现的问题:
依赖环境不一致问题:本地训练环境用了某个特定版本的库,线上推理环境版本不一致导致行为差异。解决方案是将训练和推理环境都容器化,锁定所有基础依赖的版本。
并发性能瓶颈:默认的Web框架(比如Flask)单进程处理推理请求,并发能力有限。改用Gunicorn多进程配合适当的线程模型,或直接用更高性能的推理服务框架(如ONNX Runtime、Triton Inference Server),优化效果会非常明显。
模型热更新问题:线上模型需要迭代升级,但直接替换模型文件会导致服务中断。实践中可以通过版本号管理模型文件,推理服务支持多版本并存,通过灰度策略逐步切换流量。我现在习惯在做模型服务时预留一个model_version参数,方便按需切换。
4.4 几个个人体会很深的经验
做了几个完整的“from scratch”项目后,有三条经验我觉得比任何具体技术都值得分享:
第一,日志记录是最便宜的调试工具。训练和推理过程中,在关键节点输出日志(数据shape、张量的取值范围、耗时分布),很多诡异问题当场就能定位。我见过很多同事慌慌张张在模型代码里到处打print,其实更合理的方式是一开始就把模块化的日志体系设计好。
第二,不要试图一步到位设计一个完美的系统。从能跑的最小闭环开始,逐步迭代完善,这是AI工程最务实的方法论。第一版只要能保证数据从输入到预测输出的链路是通的,就已经成功了一大半。
第三,建立自己的代码模板库。数据处理脚本、训练模板、评估函数、部署配置这些通用内容,维护一套可复用的模板会极大加速后续项目的推进速度。我在实际项目中就维护了一套自己的“AI工程脚手架”,新项目直接基于脚手架初始化,省掉了大量重复劳动。
5. 后续可以怎么扩展
5.1 从单模型到AI系统
单个模型的训练和部署只是AI工程化的起点。真正复杂的工程场景是模型与线上系统的融合:模型如何与现有业务逻辑交互、如何调度多个模型协同工作、如何处理流式数据场景下的实时推理、如何设计与前后端系统的高效接口。
这些系统级问题的复杂度会随着参与组件数量的增加而指数级上升。比如你训练了三个独立模型分别处理不同维度的需求,系统级设计需要解决的问题包括:这三个模型的调用顺序、超时处理策略、各自结果的置信度如何融合、单个模型升级如何不影响整体服务。从“单个模型跑通”进化到“AI系统稳定运转”,对架构能力的要求是完全不同量级的。
我在后续的项目迭代中逐步引入了服务网格和消息队列来解耦模型推理调用,对每个模型都增加了独立的数据监控面板。系统的稳定性和可观测性明显提升,上线新模型或迭代旧模型时也不再像以前那样如履薄冰了。
5.2 值得长期投入的方向
如果顺着“ai-engineering-from-scratch”这个大方向继续深入,有四个领域我认为值得长期投入:
- MLOps体系化建设:从手工管理实验到搭建完整的CI/CD流水线,让模型训练、测试、部署实现自动化和规范化
- LLM应用开发:基于大语言模型的应用需要一套全新的工程模式——提示词工程、RAG架构、Agent编排、上下文管理等,这是目前工程化机会最密集的方向
- 边缘端AI与模型压缩:量化感知训练、知识蒸馏、轻量化网络结构设计,让模型可以跑到更轻量的设备上
- AI系统可靠性工程:模型A/B测试、漂移检测、在线学习与自动回滚,确保AI系统在长期运行中保持稳定效果
这些方向都可以从当前项目延伸出去,底层功底仍然是前面说的那五层结构,不冲突也不浪费。基础扎实了,往哪个方向进一步深耕,更多是兴趣和业务阶段的取舍问题。