做AI工程这件事,我自己从一头雾水到能把一个完整应用从数据处理跑到线上部署,前后花了快两年。所谓"ai-engineering from scratch",我理解是两条线并着走:一条是把底层原理搞清楚,不满足于只会调API;另一条是独立把数据、训练、评估、部署这条链路走通。这两条线缺了哪一条,都算不上真正的AI工程师。这篇不是什么速成指南,而是把这条路上我认为最值得参考的路线、工具和踩坑经验完整梳理一遍——如果你刚转行、想在业务里落地AI,或者已经会调模型但没跑通过全链路,这篇就是给你写的。
1. 先搞清楚AI工程是什么:不要用研究心态做工程
我见过太多新人一上来就抱着深度学习论文猛啃,结果三个月后除了记住几个网络名字,连一个能跑的项目都没做出来。所以要聊"from scratch",第一步不是学技术,而是先搞清楚这门手艺到底是干什么的。
1.1 工程师和研究者的工作内容差别很大
很多教程把AI教学当成"前沿论文解读"来写,这给了新人一个错觉:做AI就是发论文、刷SOTA。实际上,工业界绝大多数AI工程岗位,工作重心根本不是这个。
研究者关注的是"这个模型能有多强"——新架构、新算法、新训练技巧。工程师关注的是"这个模型在真实数据上能不能稳定跑起来、跑多久、花多少钱、出了问题能不能快速定位"。我在实际项目中,真正花时间最多的三件事是:整理数据、设计评估口径、排查线上故障,真正训练模型的时间占比反倒不高。
这并不意味着研究者做的事不重要,而是说如果你走工程路线,学习重心必须调整。你当然要理解Transformer大概怎么回事、梯度下降在干什么,但更重要的是知道:数据怎么清洗才算干净,怎么划分训练验证测试集才不泄露,模型效果到底怎么评估才对业务有意义,线上预测变差了第一步查什么。
1.2 从零起步需要的基本盘
"从零"不等于"零基础也行"。我的经验是,入门前至少要具备这几样东西,不然时间成本会翻好几倍:
- 会写Python,至少能理解循环、函数、类、文件读写,能改别人的代码。
- 了解基本的Linux命令行操作,会装环境、跑脚本。
- 有耐心读英文文档——框架的官方文档、GitHub的issue,几乎都是英文。
- 数学不用怕,但线性代数和概率统计的基本概念得有:矩阵乘法、向量维度、均值方差、正态分布、条件概率。不需要会证明,但得知道这些符号在代码里长什么样。
这里有个容易走偏的地方:很多人觉得数学不好就不能学AI,于是花半年去刷《线性代数》教材,刷到行列式、特征值就崩溃了。我从实际经验说,工程岗位对数学的要求远没有那么高,你需要的是"能看懂公式转成代码"的能力,不是"能推导公式"的能力。比如你只需要知道softmax把一组数值变成概率分布,而不需要能手推它的导数。
1.3 能跑通全链路才算入门
我对"入门"的定义很朴素:给你一份原始数据和一个业务问题,你能从零开始,独立交付一个可调用的模型服务。这个定义含几个环节:数据获取和清洗、特征或预处理、模型训练和调参、离线评估、封装成API、上线后能看到日志和指标。
很多自学者卡在中间某个环节。最常见的两个崩溃点:一是数据阶段,发现真实数据脏得没法用,直接放弃;二是评估阶段,模型训练完了不知道怎么证明它"能用",随便报个准确率交差,一到线上就露馅。
所以你在学习的时候,每学一个模块都要问自己:这个东西在全链路里解决什么问题?如果有某个环节你完全没见过、不熟悉,就去动手补上。比如学完模型训练,就逼着自己用FastAPI写一个接口,把这个模型包起来跑一遍。别觉得这是多余动作,这一步能帮你把"笔记本里的模型"变成"能交付的模型",差距就在这里。
2. 零基础到能上手:我验证过的学习路线图
网上各种"AI学习路线图"很多,我这条是自己走过、也在带新人时验证过的。它最大的特点是:学一点就做一点项目,绝不在某一个阶段停留太久。学习周期大概4到6个月,每天投入两小时以上就能覆盖。
2.1 第一站:Python与数据处理实战
Python语法不用学完整本教材,我建议看基础部分后就立刻切到实际数据任务。用pandas读一份CSV,做筛选、分组、聚合、缺失值处理,再用matplotlib画分布图。这个阶段的目标不是成为Python专家,而是能搞定最核心的三件事:加载数据、清洗数据、可视化数据。
这里有一个新手常犯的错误:用Jupyter Notebook时一个格子里的代码越写越长,最后自己都看不懂。我建议从一开始就养成"函数化"的习惯,相同逻辑抽成函数,Notebook里只留主流程调用。后面做项目时你会发现,这一个好习惯能省下大量调试时间。另外一定要学会用venv或conda建隔离环境,每开一个新项目就建一个干净环境,这是避免"在我电脑上能跑"这个尴尬局面的最基本手段。
2.2 第二站:经典机器学习是绕不开的地基
我见过有人跳过经典机器学习直接学深度学习,结果训练集表现很好、测试集一塌糊涂,连"过拟合"这个概念都要临时查。经典机器学习虽然看起来"不够酷",但它把机器学习最核心的思想都浓缩在了一个极简框架里,这个框架就是sklearn的fit/predict。
你要掌握的不只是调几个模型,而是一整套方法论:划分数据用train_test_split而不是手动切;用交叉验证评估泛化能力;理解什么是过拟合和欠拟合;知道正则化是在干什么;学会看混淆矩阵、精确率、召回率、F1,而不是只看准确率。我建议你从逻辑回归和决策树入手,因为这两个模型足够简单,你能把每一个参数和预测结果对应起来,这对建立直觉特别重要。
学这个阶段不要贪多,sklearn里几十个模型,真正用到的就是个位数:逻辑回归、决策树/随机森林、GBDT系列、KMeans。重点不是背模型名字,而是理解"训练集/验证集/测试集"这个三层结构为什么是AI工程的基石——后面所有深度学习项目都会用到这套逻辑。
2.3 第三站:深度学习框架实操
选PyTorch还是TensorFlow?早几年还有争议,现在我的答案非常明确:无脑PyTorch,除非你的工作场景已经深度绑定TensorFlow生态。PyTorch的优点在于调试直观、生态活跃、Hugging Face等主流模型库都基于它,而且从研究到工业部署的路径非常成熟。
学习深度学习容易犯的最大错误是用超高层封装。很多教程让你直接调用一个现成的trainer,几行代码把BERT跑起来,训练完你什么也说不出来。我建议一定要手写一个最简单的训练循环:定义模型、定义损失函数、定义优化器,然后在一个batch的数据上前向传播、计算损失、反向传播、更新参数。这个过程别用任何高级封装,就几十行代码。写完这一段,你对深度学习"到底在训练什么"的理解就建立了,后面哪怕用再复杂的框架也不会心虚。
有了训练循环的基础,再引入数据加载器、学习率调度、早停策略、显存优化这些工程细节就顺理成章了。然后一定要学会用预训练模型:Hugging Face Transformers是目前的事实标准,从huggingface.co下载模型权重和分词器,用AutoModel和AutoTokenizer就能把主流模型跑起来。
2.4 第四站:工程化能力是分水岭
前面三站学完,你已经能把一个模型在Notebook里训练出来了。但这跟"AI工程"之间还差一大截,差的这部分就是工程化能力。我把它拆成四件事:代码管理、实验管理、模型封装、部署交付。
代码管理就是Git的基本操作,至少做到每天提交、分支清晰、不把模型权重文件传上去。实验管理的意思是,你不能靠"model_final_v3_真的最终版.py"这种文件名来记实验,而是要用参数配置或实验记录工具把每次实验的数据集、参数、指标记录清楚。模型封装是把训练好的模型包成一个服务,输入请求、返回预测结果。部署交付是把这个服务放到服务器上跑起来,能稳定响应、能看日志、挂了能重启。
我强烈建议把这四件事当成一门课来学,而不是边做边碰。因为它们每一个单独看起来都不难,但连在一起就是区分"会做模型"和"能做AI工程"的那条线。
3. 从零到部署:完整复盘一个文本分类项目
光说方法论不落地,容易变成"听懂了但不会做"。这里我把一个完整的项目从头到尾复盘一遍,项目是"电商评论情感分类",目标是给评论打上积极/消极标签。这个项目麻雀虽小五脏俱全,能覆盖全链路所有关键环节。
3.1 项目定义与数据准备
先定义问题:输入一条评论文本,输出一个二分类标签(积极/消极)。业务上更关心的是准确找出消极评论,因为这部分更值得被运营关注,所以评估指标要重点看召回率和精确率的平衡。
数据来源我用了公开的电商评论数据集,大概几万条。拿到原始数据后,第一步是数据探查:看总条数、正负样本比例、文本长度分布、有没有空值和明显重复项。这个阶段我用pandas做value_counts、describe、isnull,基本十分钟就能把数据全貌摸清楚。
数据清洗阶段有几个经典动作:去掉过短的评论(比如少于5个字的基本没有判别价值)、删除完全重复的文本、处理空值。但这里有一个我要特别提醒的点:清洗一定要留痕,每一步预处理逻辑都写成函数保存好,而不是在Notebook里手动改。因为部署后线上来的数据也需要走同样的清洗流程,你不可能让线上脚本再手改一遍。
接下来划分数据:我用train_test_split按7:1.5:1.5的比例分出训练集、验证集、测试集,固定random_state。这一步有一个我踩过的大坑会在后面单独讲,就是"划分之前做清洗、但是让信息从训练集泄漏到了验证集",这个一定要注意。
3.2 建立baseline:先跑通一条最笨的链路
很多新手一上来就上BERT,这是性价比很低的路线。我的习惯是先建一条最朴素的baseline:把文本用词频向量化,然后用逻辑回归分类。PyTorch都不用上,sklearn就够了。
做法是:用TfidfVectorizer把评论文本转成TF-IDF特征向量,设置max_features为5000左右,然后用LogisticRegression训练。整个过程不到50行代码。跑出来的结果我记得在验证集上精确率和召回率都在82%到85%之间,已经能用了。
为什么先做baseline?因为它给了你三个东西:一个"不能再差"的性能下限,一套完整的评估代码(分类报告、混淆矩阵、ROC曲线),以及一个判断后面复杂模型是否值得的参照系。如果你的BERT模型只比逻辑回归高两个百分点,那就要认真考虑计算成本和收益是否划算——很多时候业务的真实瓶颈根本不在模型。
3.3 模型升级:微调一个预训练语言模型
baseline跑通后,下一步我用Hugging Face的bert-base-chinese做了微调。具体流程是:
- 用BertTokenizer对评论做编码,设置max_length为128,padding和truncation都打开。
- 用PyTorch的Dataset和DataLoader封装数据,batch_size设为16,shuffle训练集。
- 加载BertForSequenceClassification,输出维度设成2。
- 优化器用AdamW,学习率设为2e-5,训练3个epoch。
- 每个epoch结束在验证集上算F1,选择验证集最好的轮次保存模型权重。
这里有几个关键细节。第一,分词结果一定要在划分数据集之后再生成,也就是"先划分、后编码",避免分词器在全部数据上统计信息造成隐性泄漏。第二,学习率2e-5是微调BERT时一个非常稳妥的起点,太大会导致训练不稳定,太小收敛很慢。第三,验证集指标和测试集指标一定要分开看,不要用验证集反复调参后还拿验证集报数,这是新手最常犯的数据泄漏变体。
微调后我的F1大概从84%提升到了90%左右,提升不算夸张,但已经把这条链路完整走通了。到这里,模型训练部分告一段落,真正的考验来了。
3.4 部署上线与线上监控
训练完成后的第一件事不是写接口,而是把模型文件、分词器、预处理脚本、依赖版本全部固定下来。我用了torch.save保存模型权重,同时把tokenizer的目录整个存下来。然后写了一个推理脚本,加载模型、接收文本、输出标签和概率,先在本地用几条例子验证输出正常。
接下来用FastAPI把推理脚本包成HTTP服务,暴露一个POST接口:传入JSON格式的评论,返回情感分类和置信度。再用Docker把服务打包,镜像里固定好Python版本和依赖。这一步解决的是"本地能跑"和"服务器能跑"之间的环境差异问题。
上线后监控是很多自学者完全忽略的部分。我在日志里记录每次请求的输入文本、预测结果、置信度和响应耗时。上线第一周我发现置信度普遍偏高但偶尔出现极低置信度的预测,一查发现是线上来了很多表情符号和繁体字,训练数据里几乎没有——这就是典型的线上和训练数据分布不一致。发现问题后我把这些新样本收集起来,定期加入训练集做增量更新。这个闭环才是AI工程和"训练一个模型就完事"的本质区别。
4. 工具链和资源方案:没有好装备也能干活
很多新人以为做AI必须买几万块的显卡,这真是最大的误解。我把入门阶段的工具链和资源策略完整说清楚,看完你应该心里有底。
4.1 工具链清单与各自的分工
我的日常工具箱是这些,按用途划分:
- 开发环境:Python 3.10+,PyCharm或VS Code都可以,环境管理用venv或conda。
- 数据处理:pandas、numpy、matplotlib,偶尔用seaborn做分布图。
- 经典机器学习:scikit-learn,它的API设计是所有机器学习框架的参照系。
- 深度学习:PyTorch加Hugging Face Transformers,微调预训练模型的首选组合。
- 实验管理:MLflow或Weights Biases,记录每次实验的参数和指标。
- 部署:FastAPI加Docker,轻量、好用、生态成熟。
- 协作和版本:Git加GitHub,私有仓库用仓库托管平台,代码和配置全走版本管理。
这些工具不是越多越好,而是每一个都有明确分工。我见过有人把几十个工具塞进项目,结果维护成本比写代码还高。核心原则是:每个环节选一个活跃维护、文档清晰的工具,用熟它,比什么都重要。
4.2 实验管理是纪律,不是工具问题
项目一多,你就会发现"记住上次用了什么参数"根本不可能。我有一次连续调了一周学习率和数据增强方案,最后完全分不清哪个配置跑出了最好的F1。后来我规定自己:每次实验必须在实验记录里写下数据集版本、模型类型、关键超参数、训练耗时、验证集指标和测试集指标。这个记录可以是MLflow也可以是表格,但绝不能只靠文件名记忆。
实验管理还有一个常常被忽略的价值:让实验可复现。我再也不凭空说出"上次效果挺好的那个版本跑哪儿去了",因为每个实验都有完整记录。这跟代码里固定随机种子、固定依赖版本三件事配合,才能保证上一次的结果你自己能复现。
4.3 没有GPU时的几条活路
入门阶段需要跑的都是小模型,CPU完全够用。跑BERT微调确实需要GPU,但也不是非买不可。我常用的几条路:
- 用云端公开的免费Notebook环境,跑中小规模模型完全没问题,注意会话会超时释放,记得及时保存模型权重。
- 用免费的推理API对预训练模型做调用,很多模型托管平台提供免费额度,开发调试足够了。
- 优先用小模型,比如蒸馏版BERT比完整版快好几倍,效果损失很小。工程上经常不是追求最好,而是追求够用且便宜。
- 如果必须自己训练,先用小规模数据跑通流程,再在现代算力平台上按小时租GPU。一小时的费用通常不高,别一上来就烧几千块买卡。
我见过一个很有意思的现象:没有GPU的人反而更早学会"如何把模型训练得又快又省",因为资源约束逼着你想清楚数据和模型的关系。资源受限不是劣势,反而是一种训练。
4.4 部署工具的选择逻辑
部署方案选择有个朴素的排序逻辑:优先最简单的方案,复杂度只在你真正需要的时候才加。刚开始我觉得Docker是标配,后来发现很多场景的技术栈是简化版的:FastAPI直接部署在服务器上加systemd做进程守护,其实也能稳定跑很久。只有当你要多副本、做负载均衡、不间断更新时,再引入容器编排或云原生方案。
关键是理解每一步的目的是什么。加Docker是为了环境隔离,加进程守护是为了崩溃自愈,加网关是为了流量控制和鉴权。你完全可以按需选择,不需要一口气把所有重武器都搬上。很多项目就是因为过度设计而死在部署阶段,K8s都配好了模型反而没时间调。
5. 新手高频踩坑实录与排查技巧
这部分是我最想分享的,因为文档里永远学不到。每一个坑我都亲自踩过,有的不止一次。
5.1 五个高频错误,看看你中过几个
第一个是只看准确率。二分类问题里正负样本比例不平衡时,准确率极具欺骗性。比如99%是积极评论的数据,模型无脑全判积极就有99%"准确率",但这毫无意义。一定要看混淆矩阵和F1,根据业务场景选侧重精确率还是召回率。
第二个是数据泄露。这词听起来很高深,其实就是"训练时不该看到的信息被看到"。常见来源极其隐蔽:标准化时用全量数据的均值和方差、划分前做了数据增强、文本预处理时用了全语料统计信息。我自己的惨痛教训是:有一次做关键词特征,在划分数据前先统计了全部数据的词频,然后按频率筛词表,结果验证集指标虚高了3个百分点,上线立刻现原形。
第三个是不固定随机种子。深度学习模型本身有随机性,不固定种子的话,同一个代码跑两次结果差不少,你甚至分不清改动是有效还是随机波动。更严格的做法是连依赖库版本都固定下来。
第四个是训练集表现很好、测试集一塌糊涂却不知道怎么排查。这种情况九成是过拟合,先检查训练集和测试集的数据分布是否一致,再检查模型容量是否太大而数据量不够。
第五个是代码和模型权重不放在一起管理。模型权重文件一大推,代码更新了好几版,最后模型和代码对不上号,想复现结果完全不可能。现在我会在模型文件的命名或配套文件中写下对应代码的commit号,确保任何时刻拿出来的模型都能对上当时的代码。
5.2 模型不收敛的排查顺序
训练损失不下降或者波动剧烈,几乎所有新手都会遇到。我的排查顺序非常固定,按顺序来可以最快定位问题:
- 先看数据是否有问题:标签是不是反了、样本是不是重复、有没有异常大的值。
- 再看预处理:文本编码、特征标准化有没有写错。
- 检查模型输出维度:二分类的输出维度是不是2,损失函数和标签格式是否匹配。
- 调整学习率:这是最常见的原因,学习率太大损失直接飞到NaN,太小则训练半天没什么变化。
- 检查优化器和调度器:比如Adafactor和AdamW用法不同,选错会明显影响收敛。
- 最后看batch大小和梯度裁剪:显存不够时减小batch,梯度爆炸时加梯度裁剪。
这个顺序背后的逻辑是"从数据到模型到优化":先确认喂进去的内容是对的,再确认模型结构能输出,最后才是优化层面的调整。我见过太多人一上来就调学习率,结果发现是标签编码错位了——这基本是白忙活。
5.3 数据泄露这种"隐形杀手"
数据泄露最难防,因为它不只影响指标数字,更影响你对模型真实能力的判断。它常见的几种形态我再系统列一次:
- 时间序列数据里随机打乱后切分,相当于让模型"看到未来"。
- 数据去重前就划分了训练测试集,同一个内容既在训练集又在测试集。
- 特征工程使用了全量数据的统计量,常见于标准化、归一化、TF-IDF的词表构建。
- 数据增强生成的新样本混到了验证集里。
- 人工检查测试集并反复修改模型直到"测试集也拟合"了。
我的经验是:每当感觉模型"好得不真实",就先怀疑数据泄露。验证方法也很简单:把你认为泄露的环节去掉再跑一次,看指标下降幅度。如果明显下降,说明之前的高指标确实有水分,需要修正数据处理流程。
5.4 线上性能下降的排查顺序
模型上线后效果变差,先别急着重新训练。我按这个顺序排查:
先看数据和预测分布的漂移:最近请求的文本长度、主题、来源渠道和训练数据一致吗?置信度分布有没有整体偏移?这一步能快速判断是数据变了还是模型坏了。再看代码和依赖:是不是有人改了预处理逻辑或者升级了依赖库导致行为变化。然后看服务本身:特征顺序被改变、默认参数被替换、模型文件被覆盖重载都是线上常见事故。最后才考虑重新训练:如果确认数据分布确实变化且收集到了新样本,才启动增量更新的流程。
这个排查顺序的核心思想是:先排除人为和环境因素,再怀疑数据,最后才动模型。重新训练是最昂贵的操作,不能动不动就触发。
6. 最后分享几点真实体会
写到这里,文章也接近尾声了。最后说几句心里话。
带过不少新人之后,我最大的体会是:AI工程学习路上真正劝退人的不是难度,而是"不知道自己在哪个阶段、接下来该干嘛"的失控感。所以我不建议你把这篇内容当成知识清单,而是当成一个阶段地图——现在你在哪一站,下一站该做什么,心里要有数。
还有一点是关于心态的。模型效果不好、线上出bug、数据永远洗不干净,这些都不是你能力的问题,是这个职业的常态。我到现在做新项目,第一版效果也经常不如预期,但已经不会慌,因为我知道有一套固定流程可以去排查和优化。这套流程就是你日积月累沉淀下来的工程直觉。
如果你想进一步深入学习,我的建议是把这篇提到的全链路动手走一遍,哪怕用公开数据集做一个点赞量不大的小项目,也能让你获得"从零到一"的完整体验。之后再去看更复杂的架构、更大的数据、更严苛的性能要求时,你已经有了一根可靠的主心骨。这条路不短,但每一步都算数。