1. 为什么想不开要搞“AI工程从零开始”
看到“ai-engineering-from-scratch”这个标题,我第一反应是:好家伙,又是一个从零开始的伟大计划。这些年类似的项目多如牛毛,有人从零手写神经网络,有人从零复现论文,但真正能坚持到“工程化”这一步的人其实很少。原因很简单:学AI理论和做AI工程,是两件难度曲线完全不同的事。
理论阶段你会觉得每天都在打开新世界,梯度下降、反向传播、注意力机制,每个概念都让人兴奋。但一旦进入工程阶段,画风就变了:环境依赖冲突、数据格式不统一、模型训练完没法部署、部署完效果又对不上,这些才是AI工程的真实日常。做“from scratch”不是要你把PyTorch重写一遍,而是把一个AI项目从想法到落地的全流程亲手走通,搞清楚每个环节为什么要这么做,踩过的坑到底在坑什么。
这个项目适合三类人:第一类是刚学会Python、跑过几个教程但始终停留在“能运行”阶段的人;第二类是搞算法研究但总被工程问题卡住、想补齐工程能力的人;第三类是准备转行AI工程岗、想在简历上有一份完整项目的人。如果你只是想在本地跑个demo截图发朋友圈,那不用看这篇文章。但如果你想把一个模型真正变成可以交付、可以迭代的东西,这篇文章大概能帮你省下几个月的摸索时间。
接下来我就按自己实际走过的路径,把这个“AI工程从零开始”拆开讲清楚,包括环境怎么搭、数据怎么管、模型怎么训、服务怎么部署、上线后怎么盯,以及过程中那些文档不会写的坑。
2. 基础能力准备:别一上来就啃花书
2.1 数学基础其实只差这几块
很多人在AI门前徘徊,是因为被“需要高数、线代、概率论基础”劝退了。说实话,如果你不走研究员路线,做AI工程需要掌握的数学并没有想象中那么深。线性代数里最重要的是矩阵乘法和维度变换,因为张量操作本质就是维度游戏;概率统计里你主要得理解分布、期望、方差和最基础的贝叶斯思想;微积分部分会算导数、理解梯度和链式法则就够了,深度学习框架帮你把反向传播都算好了。
我的建议是先学“够用”的部分,不要等数学全书学完再动手。我是边做边补的:训练时过拟合了,回去补正则化和偏差方差理论;做数据增强时,回去补分布变换;看优化器文档时,回去补动量和学习率衰减。用项目驱动学习比啃书效率高太多了,书留着当工具书查就行。
2.2 机器学习核心概念要补扎实
AI工程绕不开一些核心概念,这些概念是后续所有工程决策的理论依据。训练集、验证集、测试集怎么划分,涉及数据泄漏和模型泛化能力评估;过拟合与欠拟合,涉及正则化、早停和模型容量调整;偏差和方差,涉及调试时优先看哪个指标;评估指标的选择,分类问题不能只看准确率,回归问题要看MAE还是RMSE,都要结合业务场景。
概念不牢的人做工程很容易犯一个错:模型在测试集上跑分很高,一上线就崩。那不是模型不行,是你在离线评估时就埋了雷——数据泄漏、样本不独立、评估切分错误,都是新手高频问题。后面我会单独开一节讲这些坑,这里先记住一句话:评估流程不可靠,模型性能就是空中楼阁。
2.3 Python工程化:从脚本到项目的关键跨越
写数据分析的脚本和写AI工程代码是两种思路。脚本是一次性的,数据在、环境在、模型权重在,怎么跑都能出结果。但工程代码要面对的是:别人怎么复现?三个月后的自己怎么接手?服务挂了怎么排查?
我建议从零开始就按工程规范来写。项目结构上,把数据、代码、模型、配置分开目录管理。代码层面,把数据处理、模型定义、训练逻辑拆成独立模块,不写那种一坨几百行的训练脚本。命名清晰、函数单一职责、配置文件不写死在代码里,这些老生常谈的东西在AI项目里尤其重要,因为AI项目的链路比普通Web项目长得多,任何一个环节出问题排查起来都让人头大。
3. 环境与工具链:把“能在本地跑”变成“能稳定复现”
3.1 虚拟环境与依赖管理:从源头杜绝依赖地狱
Python的依赖管理是AI工程第一道坎。有读者跟我说过,他一个项目里TensorFlow要2.x,另一个项目要1.x,装了又卸、卸了又装,最后系统自带的Python环境被折腾得乱七八糟。这不是技术问题,是没做环境隔离。
我的标准方案是每个项目建独立虚拟环境。Python自带venv可以用,但我更推荐选择适合项目需求的虚拟环境工具来隔离环境依赖,因为AI项目除了Python包,还可能涉及CUDA版本、驱动版本,这些不是你项目内的虚拟环境能管的。不同框架对CUDA要求不一样,给每个项目配一个独立的环境,省心得多。刚入门时建议用Anaconda或Miniconda,它不光能管Python环境,还能管CUDA工具链,这对后续跑深度学习项目很重要。
依赖管理方面,固定的原则是:记录顶层依赖,用锁定文件固定版本。不光要锁主框架版本,还要锁传递依赖版本,否则半年后拉下来谁也不知道装的是哪版。如果项目需要分享或部署,用镜像源提高下载速度,但别为了省事把所有包都装最新版,深度学习框架的大版本升级经常不兼容旧代码。
3.2 数据管理:数据是AI工程的起点
很多人从零做项目时完全不重视数据管理,训练集放在一个文件夹里,验证集放在另一个文件夹里,靠文件夹名字区分版本。数据集换了一版,代码里的路径要改,模型结果要对齐,简直是一场灾难。
正规的做法是用数据版本管理工具,比如DVC。数据文件不像代码那么小,不适合放进Git,DVC就是干这个的:它记录数据文件的元数据和版本关系,数据本身存在本地或者远程存储。每次训练之前,明确记录当前用的是什么版本的数据集,跑出来的模型才能对应得上。
数据层面还要做基础的质量检查:有没有空值、有没有重复样本、标签分布是否合理、特征范围是否异常。这些检查写成一个脚本,每次数据更新后自动跑一遍,能省掉很多后面排查问题的痛苦。我见过太多人花几周调模型,最后发现是数据本身有问题,那个滋味真的不好受。
3.3 实验追踪:让每一次尝试都有记录
做AI工程最怕的是“这个效果好像比之前好,但我不记得当时改了啥”。手动记录实验参数不是不行,但人总有懒的时候,一懒就漏,一漏就没法复现。工具层面我建议老老实实用实验追踪工具,MLflow、W&B都行。
我自己习惯用MLflow,因为它是开源方案,可以存在自己的服务器上,隐私和数据安全都更可控。配置好之后,每一轮训练自动记录:超参数、模型结构、训练集和验证集指标、模型权重、代码commit号、使用的数据集版本。有了这些信息,后续做对比、做回滚、做报告都有据可依。这个习惯看起来增加了一点工作量,但它是AI工程从“野路子”走向规范化的分水岭。
4. 实操项目:从零走通一个AI工程全流程
4.1 项目选择与问题定义
从零学AI工程,不建议一上来就挑战大模型、自动驾驶这种庞大课题。我的建议是选一个端到端可闭环的小项目:数据能拿到、问题能定义、模型适中、能部署、能评估。比如房价预测、客户流失预测、图像分类这类经典任务是很好的起点。
以房价预测为例,问题定义是:给定房屋属性特征,预测成交价格。这是一个回归问题,评估指标可以用RMSE或MAE。任务定义清楚之后,后续的每一步才有评价标准:模型好不好,不是“我觉得行”,而是指标是否达到预期、是否在业务上合理。
这个环节很多人会忽略“业务指标”和“模型指标”的区别。业务上你可能关注预测误差在房价5%以内,而模型指标RMSE是绝对误差,阈值怎么定需要结合数据分布。如果数据里既有10万的房子又有1000万的房子,RMSE会被高价位样本主导,这时候可能需要看加权指标或者按比例误差来评估。定义问题时想清楚这一点,后面才不会白做。
4.2 数据和特征工程实操细节
数据拿到手的第一步是探索性分析,你要看数据的形状、类型、缺失情况、分布情况。房价预测数据里常见的问题包括:部分特征缺失(比如有些房屋没有车库面积)、离群值(比如一套房面积5000平米)、类别特征没有编码、数值特征量纲差异大。
缺失值处理有几种常见策略:删除缺失率过高的列,用均值/中位数填充,或者用模型预测填充。选择哪种不是拍脑袋的,要看缺失机制和缺失比例。离群值处理要谨慎,得判断是真的异常还是真实的极端值,一刀切删除可能丢掉重要信息。类别特征用独热编码还是标签编码,取决于类别是否有顺序关系。
特征工程的目的是帮模型更好地理解数据。做房价预测时,我通常会给模型一些衍生特征,比如房屋单价、房龄、单位面积房间数。这些特征本身有没有用,不能靠猜,一个原则是让特征的变化趋势能反映目标值的变化趋势。另外数值特征归一化对深度学习模型很重要,但对树模型的影响相对小,这要根据模型类型来定。
4.3 模型训练与评估的完整流程
对新手来说,我强烈建议先用简单模型跑通baseline,再上复杂模型。以房价预测为例,先用线性回归跑一版,看着各项流程打通了,再换随机森林、XGBoost或者简单的神经网络。这样做的意义是:先在简单模型上建立正确的评估流程,再逐步增加模型复杂度,避免一上来就被模型本身的问题绕晕。
数据划分上,用训练集和测试集的划分策略,要保证分布一致。时间序列数据不能用随机切分,要用时间窗口切分,这是新手很容易踩的坑。训练过程中要关注训练集和验证集指标的变化趋势:训练集误差低、验证集误差高,是过拟合;两个都高,是欠拟合或者特征工程不足。
训练完成后的评估不能只看一个指标。回归任务我习惯同时看RMSE、MAE和R²,三个指标各有侧重:RMSE对大误差敏感,MAE反映平均绝对误差,R²反映模型解释力。还要画预测值对真实值的散点图,直观看到模型在哪些区间偏了。这一步做的越仔细,后面部署上线越有底气。
4.4 把模型包装成可调用服务
模型训练好了,总不能一直躺在Jupyter Notebook里。部署是工程化的关键一步。最简单的部署方式是把模型封装成一个HTTP服务,我推荐使用FastAPI和uvicorn的组合,简洁高效,天生支持异步,性能也不错。
流程是:加载训练好的模型权重,定义输入的请求格式和数据校验规则,写一个预测接口,接口内部做与训练时完全一致的数据预处理,返回预测结果和对应的说明。这里最容易出的问题是预处理不一致:训练时你对特征做了标准化、填充了缺失值,部署时这些步骤也要原封不动地执行,而且要把训练时学到的填充值和标准化参数保存下来,预测时读取使用,而不是重新计算,否则预测结果就会偏差。
接口写完之后,本地跑一遍测试,用curl或直接浏览器访问接口地址,传一条样本数据,确认返回结果正确。这个步骤看起来简单,但它是连接模型和业务的桥梁,桥搭不好,后面什么监控、迭代都无从谈起。
4.5 容器化:让模型在任何机器上跑起来
本地接口能跑通只是第一步,你要让这个服务换一台机器还能跑,才算真正的工程交付。最通用的方案是Docker容器化。Docker可以把你的代码、依赖、模型文件、运行环境全部打包成一个镜像,在任何安装了Docker的机器上都能一致运行。
写Dockerfile的关键点是:基础镜像选择要匹配你的框架要求,尽量选官方镜像;依赖安装放在代码拷贝之前,利用构建缓存机制加速构建;模型文件通过挂载卷或打包进镜像的方式要权衡,模型文件太大时不适合直接打包,用挂载或远程拉取更合理;容器内的端口要映射到宿主机才能访问。
我踩过的坑是镜像构建时间过长和镜像体积过大。后来优化方案是:基础镜像用最小化的运行镜像,依赖分阶段构建,先构建包含编译依赖的镜像,再把编译产物拷贝到运行镜像。这样镜像体积能小不少,构建速度也快很多。
5. 部署上线后的运维监控与模型迭代
5.1 模型监控:上线只是开始
模型上了线,很多人觉得大功告成,其实这正是另一个阶段的开始。模型在真实环境里的表现和离线评估往往存在差异,因为线上数据分布和训练数据分布不会完全一样。你需要监控的核心指标包括:请求量、响应延迟、预测结果分布、输入数据的特征分布、业务侧反馈的错误率。
监控工具可以用Prometheus加Grafana这一套,技术栈通用、社区成熟。不太复杂的情况下,也可以用简单的日志统计和定期汇总脚本。不管用什么工具,必须做到异常可感知:特征分布突变、预测结果偏差加大,都要能触发告警。否则模型悄悄失效,业务影响很严重的时候你才发现,那就晚了。
5.2 数据漂移与模型迭代策略
数据漂移是线上模型效果下降的头号原因。什么叫漂移?就是线上真实数据的分布慢慢和训练数据不一样了。比如房价预测模型训练时市场平稳,但后来某个区域房价暴涨,这个区域的样本在训练集里没见过,预测自然不准。
应对策略包括:定期从线上收集样本加入训练集做增量训练或全量重训;设定一个模型性能监控指标阈值,比如每周预测误差超过某个值就自动触发重训流程;建立定期人工抽检机制,评估模型在最新样本上的表现。模型迭代不是“训一次就用到地老天荒”,而是要形成数据回流的闭环机制。
这就要求你在最初设计项目时,就想好线上数据怎么回流、怎么标注、怎么进训练集。很多从零开始的工程没考虑这一环,到后面想迭代时数据都丢光了。把数据回流设计进系统里,才是AI工程和AI业余项目的分水岭,也是真正体现“工程”二字价值的地方。
6. 新手最容易踩的坑与排查思路实录
6.1 依赖冲突与“在我机器上明明能跑”
这个问题出现的频率高得离谱。现象是:本地跑得好好的代码,换一台机器或换一个环境就报错。原因绝大多数是依赖版本不一致,或者系统库缺失。
排查思路很明确:第一步看完整报错信息,找到是哪个包加载失败;第二步确认环境是否干净,有没有全局环境的污染;第三步用锁定文件重新安装依赖,锁定文件应该是你项目的一部分;第四步检查系统级依赖,比如某些Python包需要系统库支持。别一上来就重装整个环境,那会浪费大量时间。
6.2 Offline评估指标虚高:数据泄漏的锅
很多人模型在测试集上表现很好,上线就崩,第一反应是线上环境有问题,其实往往线下就有问题。最常见的原因是数据泄漏:训练时用了未来的信息,或者训练集和测试集之间发生了信息交叉。
举两个真实例子:一是做时序预测时,对数据做全局标准化,用了未来数据的统计值,这就是泄漏;二是在做缺失值填充时,用全量数据的均值填充,包括测试集的部分,这也是泄漏。判断数据泄漏的一个技巧是:如果离线指标好得不可思议,比如准确率接近100%,大概率有泄漏。处理方式是严格保证处理流程不跨数据子集,所有统计量都只在训练集上计算。
6.3 训练与推理不一致:模型部署隐形的炸弹
模型训练时效果好,部署后单条预测结果完全不对,最常见的根因就是训练和推理时数据预处理逻辑不一致。训练时你对特征做了标准化,推理时忘了做;训练时对缺失值做了填充,推理时没填;训练时特征列的顺序是A-B-C,推理时换成了A-C-B,模型就会混乱。
解决这个问题的根本办法是:把数据预处理逻辑封装成独立的模块,训练和推理共用同一份代码;把训练时学到的参数(标准化均值和方差、填充值)落盘保存,推理时用保存的参数做处理。测试时一定要用一条原始未处理的数据从头走一遍推理链路,验证输出合理。
6.4 GPU显存不足与训练进程崩溃
训练深度学习模型最常见的问题就是显存不足,报错信息一般是CUDA out of memory。遇到别慌,优先检查:是不是其他进程占了显存,用相关命令查看显存占用情况;批处理尺寸是不是设得太大,调小一些再试;输入数据的维度是不是异常膨胀;有没有累积梯度导致的计算图一直不释放。
另一个训练稳定性的问题是损失值震荡或变成NaN。常见原因有学习率设太大、数据里出现NaN或无穷值、网络结构数值不稳定。我的排查顺序是:先检查数据有没有异常值,再调低学习率,再看梯度是否爆炸。加了梯度裁剪和合理初始化之后,大部分训练稳定性问题都能解决。
6.5 实验记录混乱
这个坑属于管理和习惯问题。很多人的实验记录方式是:一堆带日期的文件夹,加上“最终版”“最终版2”“真的最终版”这种命名。这种习惯在项目小的时候还可以忍受,一旦实验数量上去,根本分不清哪个模型对应的哪套参数。
避免这个坑最有效的方式就是尽早养成实验追踪的习惯。每跑一个实验,记录目标、参数、数据版本、结果指标、结论备注。这个习惯刚开始可能会觉得繁琐,但坚持两周之后你就离不开它了。做AI工程本质是做科学实验,实验不记录,等于白做。
7. 延续话题:从零到一之后,路还长
文章写到这里,核心的“AI工程from scratch”路径基本走完了。按这条路径,你至少会有一整套跑通的项目:虚拟环境、版本管理、数据管理、实验追踪、训练评估、接口封装、容器部署、监控报警,这些合起来才是AI工程的全貌。
我个人最大的体会是,从零开始最难的从来不是模型本身,而是工程链条的完整度和规范性。模型技术更新换代很快,今天用某个模型,明天可能就有新架构出来,但工程化的方法论是长期稳定、跨项目通用的。你学会怎么管数据、怎么追踪实验、怎么做部署、怎么监控迭代,这些东西换任何一个AI项目都成立。
所以如果你真的打算认真走这条路,别急着追逐最新的模型和论文,先把一条最小的工程链路走通,哪怕是个简单的房价预测,把它做得工程化、体系化,比跑通十个demo更有价值。后面再接触大模型、多模态、推荐系统,你会发现骨架是类似的,只是数据形态和模型结构变了,你已有把项目做扎实的工程能力做底座,新东西学起来会顺手得多。
最后再分享一个小经验:学着把每一个项目完成的过程记录下来,错误、排查思路、解决方案都写下来。这些记录不只是写给读者看的,更是写给未来的自己。AI工程是个实践性极强的领域,踩过的坑、趟平的路,回头看都是你区别于新手最宝贵的积累。