ARTICLE · INTELLIGENCE

战地情报 · 详情页

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

AI工程从零开始:核心误解、技术路线与实战指南

AI工程从零开始:核心误解、技术路线与实战指南

1. “AI工程”在从零开始时,最容易被误解的三件事

1.1 核心需求解析:这不是研究岗位,而是工程岗位

打开GitHub看到“ai-engineering-from-scratch”这个标题的时候,我第一反应是:这个仓库想解决的问题,其实是很多人的集体困惑——明明看了大量深度学习教程,跑通了几个Notebook,甚至还能调几句Transformer的代码,可一旦脱离教程环境、脱离Kaggle比赛,真的面对“一个有业务目标、有数据限制、有部署要求”的任务时,整个人又会陷入“会做但又不会做”的尴尬状态。

我见过太多人把AI工程理解为“会用PyTorch调模型”,但真实工程里的比重,模型训练可能只占20%,剩下的是数据处理、评估方案、服务化部署、监控迭代。这也是我为什么特别偏爱“from scratch”这个定位——它暗示的并非从零手写算法,而是从零搭建起一套完整的、能落地的AI工程能力体系。

真正的AI工程,起点是“明确要解决什么问题”,终点是“系统稳定运行并持续产生价值”,绝不是“把模型精度刷到99%就交差”。所以这个项目的核心需求可以拆成四块:第一,理解机器学习与深度学习的基本原理,不是在黑盒里调参;第二,掌握数据清洗、特征工程与Pipeline建设能力;第三,训练、评估、调优模型,并建立可复现的实验流程;第四,学会把模型封装成接口、部署到线上,然后持续监控和迭代。

1.2 真正的难点在数据与工程化,不在模型

很多从零开始的人会本能地认为,最难的是“模型的结构和理论推导”。实际上,你在网上随便就能找到ResNet、Transformer的源码和讲解,模型结构在今天已经成了“公开的知识”,反而是数据问题让人头痛。真实项目里,数据是脏的、不均衡的、字段缺失的、时序错乱的,甚至标签本身都是错的中文规则建模,数据多样性与覆盖度评估,流式特征还是批量特征。

我自己的一个实际体会是:训练脚本改10行可能只需要20分钟,但为了搞明白为什么线上效果比离线差5个点,可能得花掉两三天,最后发现是训练集和预测集的特征分布不一致。这种情况在从零开始时特别常见,因为你没有建立“数据版本管理”和“特征一致性校验”的习惯。

1.3 从零开始的目标边界:学得会,但要留足时间

如果这颗仓库是完全零基础的路线图,那一定要对“时间预期”有个清醒认识。不是说你学三天Python就能上手Transformer,而是说如果你每天投入2到3小时,按“数学底子→经典机器学习→深度学习原理→工程化实践”的顺序走,大概3到6个月能形成完整的工程能力。别信那些“30天成为AI专家”的宣传,AI工程是典型的慢变量,它需要的是“持续可积累的长期主义”。

我这里有一个比较现实的判断标准:当你拿到一份新的数据集,能独立完成“清洗—特征构造—基线模型—迭代优化—结果评估”的完整闭环,并且每个环节都知道自己在做什么、为什么这么做,这时候你才算真正入了AI工程的门。

提示:如果你本来就有不错的编程基础和数学功底,这个周期可以压缩到两个月左右;如果完全是零基础,请一定先打好编程底子,不要在还写不出类的时候就冲进模型训练阶段。

2. 动手前的技术栈选型:先学什么、后学什么

2.1 数学基础:只学“够用”的部分

提到数学,很多想转行做AI的人立刻被吓跑。我可以负责任地说:不需要为了AI工程去啃完一整本数学分析。但有些东西绕不开,必须建立一个直观理解:线性代数中的矩阵乘法、向量空间、特征值;概率论中的条件概率、贝叶斯思想、期望与方差;微积分中的导数、偏导数、链式法则;最优化里的梯度下降概念。

我用一个生活化类比来解释为什么这些数学有用:线性代数负责的是“多维数据的表示与变换”,模型内部的基本运算就是矩阵乘法,你把一批样本乘一个权重矩阵,再经过激活函数,其实就是在做空间变换;概率论负责的是“不确定性的量化”,模型输出的不是确定的答案,而是一个概率分布;微积分负责的是“如何让模型变好”,反向传播的本质就是求损失函数对每个参数的偏导数,然后按梯度方向更新。这三块是模型的骨架,缺了任何一个,你都只能“套用现成代码”。

不建议一上来就抱着教材埋头刷题,更高效的做法是“用啥学啥”。比如你在看梯度下降时,发现自己看不懂偏导,再回头去翻微积分里对应的那一节;你在做Embedding相似度计算时,发现不懂余弦相似度,再去补向量空间的概念。这叫“按需学习”,效率远高于系统从头学。

操作系统层面准备一个Linux环境(Ubuntu或Debian都能下载到),配置Python 3.9以上版本,建议直接用Miniconda管理环境。Windows上也能做,但后续如果涉及到Docker、GPU驱动、线上环境复现,你会被Windows的“边界模糊问题”折腾到怀疑人生。我自己的习惯是一律在Linux下训练,Windows只用来写文档和做轻量级编辑。

2.2 编程基础与工具链配置

编程语言首选Python,这没有争议。但注意,AI工程里的Python,不只是“会写循环、会调库”,更关键的是:熟练使用NumPy操作多维数组,会写整洁的函数式代码,理解类的基本用法,掌握文件读写和日志记录,会用虚拟环境管理依赖。

工具链上,我的推荐列表是:Jupyter Notebook适合探索和可视化,但正式训练脚本必须写成.py文件;VS Code加Remote-SSH插件用来远程开发;Git必须从第一天就开始用,每次实验都记录代码变更;Weights & Biases或者TensorBoard用来记录实验指标。这套组合,才是AI工程师日常的“工作台”。

不要把自己变成“Notebook工程师”。训练流程、数据处理逻辑、模型定义必须沉淀成模块化脚本,Jupyter只负责快速验证和画图。否则当你需要复跑三个月前的一次实验时,你会发现自己面对的是一个巨大的、没有结构的.ipynb文件。

2.3 深度学习框架的选择逻辑

框架选择上,我建议从PyTorch入门,而不是TensorFlow或Keras。理由不是“哪个更好”,而是PyTorch的“动态计算图”对初学者理解反向传播更友好,调试时你可以用Python原生的print和pdb直接看中间变量,心智负担小很多。当你理解了底层的训练逻辑之后,再去看TensorFlow、PaddlePaddle或者JAX,基本就是“同构异表”的关系。

还有一个容易被忽略的点:从零开始的时候,不要一上来就拥抱高级封装库。比如PyTorch Lightning这类框架虽然能帮你省掉很多模板代码,但也把“训练循环内部到底发生了什么”藏了起来。我的建议是前两三个项目老老实实用原生PyTorch手写训练流程,等理解了fit、validate、test这些环节的本质,再引入高级封装让你事半功倍。

3. 核心知识拆解:从线性回归到Transformer的路线图

3.1 机器学习核心概念:损失、梯度与过拟合

先从最简单的线性回归讲起。为什么几乎所有AI入门资料都从它开始?因为它把机器学习最关键的三件事全部串起来了:模型结构、损失函数、优化方法。模型结构就是“y = wx + b”;损失函数衡量预测值与真实值的差距;优化方法通过梯度下降不断调整w和b让损失变小。理解了这一步,你就理解了AI训练的本质。

接下来就要接触过拟合这个“伴随一生的敌人”。我做一个直观描述:过拟合就是模型把训练集里的细节和噪声背下来了,却没学会泛化规律。表现是训练集loss很低,验证集loss很高。应对手段也相对固定:增加数据量、降低模型复杂度、正则化、Dropout、早停。在从零开始阶段,你要养成的第一个“模型健康检查习惯”,就是每训练几轮就打印一次训练集与验证集的指标,观察两者是否差距过大。

评估指标的选择也是新手最容易踩坑的点。分类问题常用准确率,但类别不平衡时准确率是骗人的;回归问题用均方误差,但异常值会拉高它;推荐场景更看重排序指标。工程上,指标必须跟业务目标绑定,比如你做一个“识别风险交易”的模型,关心的不是98%的正确分类,而是“高风险交易里真正被你拦住的比例”以及“误伤了多少正常交易”。从零开始就建立这种“指标即业务语义”的意识,非常宝贵。

3.2 神经网络:从感知机到残差网络的身份演进

从线性模型到神经网络,核心跨越是引入了非线性激活函数。线性模型再复杂也只是线性组合,无法处理非线性关系;加入ReLU之后,多层网络就能逼近任意复杂函数。这一段的实操重点,我建议手写一次反向传播。你可以纯用NumPy实现一个两层神经网络,前向传播算一遍损失,然后手动推导梯度更新公式,再用PyTorch自动求导验证你的结果是否正确。这一步能直接打通“数学如何变成代码”的最后一公里。

当网络加深后,会遇到梯度消失和梯度爆炸,这也是深度学习发展史上极其关键的一个转折。ResNet的思想是用一个“恒等映射的残差连接”让梯度更容易回传,BatchNorm则把每层输入分布拉回标准范围。这些设计每一个都有清晰的“为了解决什么问题”的背景,而不是拍脑袋想出来。这也是我在这个项目里特别强调“原理优先”的原因——你只有知道模型结构是为哪个痛点设计的,才能在真实问题上做出正确的结构选型。

3.3 数据工程:pipeline之上,稳定与复现是王道

AI工程和AI科研最大的区别在于:后者追求“新”,前者追求“稳”。你的模型再花哨,如果训练数据在不同batch之间出现了重复或顺序泄露,结果就是不稳定的;如果训练集和测试集来自不同时间段,覆盖了不同分布,那评估结果就完全不可信。数据 Pipeline 的第一优先级永远是“可复现”。这里我推荐一套可复用的数据工程模板:原始数据单独存放并做哈希校验,清洗逻辑写成独立脚本,特征处理保存参数(如均值、标准差),训练测试划分固定随机种子,产出的特征表保存版本号。

如果你处理的是结构化数据,Pandas的坑必须提前知道:合并操作造成索引错乱,缺失值填充逻辑影响分布,DataFrame与NumPy之间的隐式转换。如果你处理的是图像或文本,相应规范又会不同。从零开始,先精通一种类型的数据即可,但“上瘾于在内存里拖拽DataFrame”不代表你理解数据链路,请务必理解数据从磁盘到内存再到GPU的完整流转。

3.4 评估与调参:把实验变成一门纪律

我做AI工程最深的体会就是:真正拉开“业余”和“专业”差距的,往往不是谁的模型更高级,而是谁的实验更严谨、记录更清晰。每跑一次实验,你至少要记录:数据版本、代码版本、超参数、随机种子、训练时长、模型参数总量、训练集和验证集指标、GPU型号与显存占用。

超参数的优化顺序也有讲究。第一个要看的是学习率,它直接决定了训练是否收敛;其次是batch size,影响梯度估计的稳定性与训练速度;再次是网络结构层数和通道数。不要一上来就套网格搜索,而是先用少量的实验估算各参数的敏感度。对新手来说,学习率设置太高会出现loss震荡甚至发散,设置太低则训练半天loss纹丝不动,这也是“训练失败”最常见的两个原因。

早停是一个非常实用但常被忽略的策略。我的习惯是设置一个patience值,比如验证集指标连续5个epoch都没有提升就停止训练,然后回滚到表现最好的那个epoch的权重。这个逻辑简单但极其有效,既能防止过拟合,还能节省大量时间资源。

3.5 部署与MLOps:工程化的终点

模型训练完只是“万里长征走了一半”。部署环节从零开始要掌握的核心内容包括:模型导出(TorchScript或ONNX)、API服务编写(FastAPI)、容器化(Docker)、小规模压测以及“模型监控”的基础思路。为什么要讲这一块?因为线上系统面对的是实时数据,数据分布会漂移,模型性能会衰减,你需要知道如何监控并决定何时重训。

有一个容易忽略的陷阱:训练代码和推理代码必须严格同源。很多人训练时做了一系列数据预处理,部署时又重新实现了一遍,前后逻辑不一致,线上结果崩盘。解决方式是在代码层面把“预处理→模型推理→后处理”封装成同一个推理函数,训练和部署都用它。

4. 从零到可部署项目的完整实操流程

4.1 项目规划与数据集准备

从零开始时,不要一上来就挑战“图像生成”或“大语言模型微调”,这种项目训练成本高、调试难度大,很容易劝退。我推荐第一个完整项目选一个二分类问题,比如“信用卡欺诈检测”或者“垃圾短信识别”,这类问题数据集容易获得、模型规模适中、效果好做量化对比。项目周期控在一到两周内,目标不只是“训练出一个模型”,而是“跑通一个完整的AI服务”。

我以一个“中文文本评论情感分类”为例,说一下实操流程。数据集可以用酒店评论或电商评论,大概一万条,正负标签均衡。数据准备阶段要做的事:统一编码格式、清洗特殊字符、按比例划分训练/验证/测试集并固定随机种子。划分之后马上做一个分布检查,确认三个集合的标签比例基本一致,并用相同方式统计样本长度分布,避免验证集和训练集来自不同分布。

4.2 特征提取与模型训练闭环

中文文本分类可以使用TF-IDF特征加简单模型作为第一个基线,这非常关键。基线模型的目的是“让后续所有复杂方案有对比对象”。设计流程如下:

from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.linear_model import LogisticRegression from sklearn.pipeline import Pipeline model = Pipeline([ ("tfidf", TfidfVectorizer(max_features=5000, ngram_range=(1, 2))), ("clf", LogisticRegression(C=1.0, max_iter=1000)) ]) model.fit(X_train, y_train)

选择LogisticRegression而不是上来就上BERT,是因为它训练快、可解释性强,能帮你快速验证“数据有没有洗干净”“标签是否可靠”。跑完基线后看验证集F1分数和混淆矩阵,如果基线就达到0.9以上,那说明任务偏简单;如果很低,很可能问题出在数据而非模型。

接下来进入深度学习方案。用PyTorch实现的方式是:一个embedding层加一个双向LSTM或TextCNN,在训练循环里记录train loss、val loss、f1分数,配合早停输出最优模型。这里有一个很实用的建议:先用200条样本过拟合跑10个epoch,如果模型能在这200条上学到头,说明代码逻辑没有bug;如果连这个小样本都无法拟合,就不要浪费算力去做更大规模的训练了。

训练完成后,务必检查案例级别的错误。随机抽取20条预测错误的样本,人工看一遍,你会发现“标注噪音”和“语义边界案例”占了很大比例,这些观察会直接反哺到数据处理和标签清洗策略里。这也是AI工程中“以错误驱动优化”的核心思路。

4.3 推理接口与Docker部署

模型验证通过后,用FastAPI封装一个推理接口。注意接口设计要对齐业务:请求应该传原始文本,接口内部完成预处理、模型推理、后处理,返回“负面/正面”标签和置信度。不要暴露中间层向量或原始模型输出给调用方。

from fastapi import FastAPI from pydantic import BaseModel class Review(BaseModel): text: str app = FastAPI() @app.post("/predict") def predict(review: Review): label, prob = infer(review.text) return {"label": label, "confidence": prob}

Docker化的时候,有两个容易踩的坑。第一,模型文件一定要打进镜像或从受控的对象存储下载,不要在容器启动时依赖外部临时路径;第二,基础镜像要选包含正确Python版本和依赖的镜像,用requirements.txt锁定依赖版本,逐版本排查兼容性。构建镜像时精简依赖体积,别为了图省事把整个训练环境打包进推理镜像。

部署完成后,我还会用一个简单的脚本模拟不同来源文本的请求,进行1000次循环压测,记录平均延迟和P95延迟。如果超过你的业务门槛,比如50毫秒以内,就需要考虑模型简化、量化或者加缓存了。这不是“优化到极致”,而是让你建立“延迟预算”的工程概念。

5. 常见问题与排查技巧实录

5.1 训练阶段典型问题速查对照

我整理了从零开始做AI工程最常见的问题,以及对应的解决思路,做成一张速查表,方便你在遇到紧急情况时快速定位。

现象可能原因排查步骤与解决思路
训练loss不下降学习率过小或过大、模型结构bug、特征未归一化先用小样本过拟合,打印每一层的梯度数值范围;尝试学习率按数量级扫描
loss波动剧烈学习率过大、batch size过小降低学习率2到5倍;适当增大batch size
训练loss下降但验证loss升高过拟合增加正则化、Dropout、数据增强,启用早停
训练和验证指标对不上代码逻辑数据划分或预处理泄漏核对训练/验证集划分的随机种子,检查预处理函数的输入范围
部署后效果与离线差异大推理与训练预处理不一致、特征分布漂移强制使用同一个推理函数;对线上输入做分布统计,与训练集对比
显存不足batch size过大、序列过长、模型过大减小batch size,使用梯度累积,必要时做混精度训练
收敛速度极慢特征尺度差异大、模型初始化不好标准化特征、检查是否该用更合适的优化器(如AdamW)

5.2 几个我踩过、且极少写在文档里的坑

第一个坑:随机种子的“伪复现”。一开始我以为固定了Python的random和PyTorch的manual_seed就能让实验结果完全一致,后来发现换GPU型号后结果仍然不同,一些底层运算(比如cuDNN的卷积实现)是随机选择算法的。规避办法:固定所有能固定的种子,同时把“实验结果的可变异范围”当成正常工程现象。真正关键的不是让两次训练一模一样,而是让几次重复实验之间的指标波动在一个可接受的范围内。

第二个坑:数据泄露,最隐蔽的“脏数据”。我在做一个时间序列预测项目时,离线验证指标好得反常,后来才发现我在构造滑动窗口特征时,无意中把“未来几期的目标值”也卷进了特征里。这个坑极其隐蔽,因为它不会报错,你只会看到模型“异常优秀”。排查技巧很简单:在训练特征里故意加入几列“下一时刻的真实标签对应的数值”,如果模型效果显著提升,说明你的特征构造存在未来信息泄露的风险。

第三个坑:模型文件版本管理混乱。训练过程中会不断生成model_1.pth、model_final.pth、model_final_v2.pth这种文件,时间一长连自己都分不清哪个对应哪个实验。我的做法是给每个实验建一个独立目录,目录名包含“模型结构+数据版本+日期”,权重文件统一命名best_model.pth,配套的config.yaml里记录超参数。这不是美观问题,是工程可复现性的基石。

5.3 关于学习路线与心态的几条经验

从零开始最怕两件事:一是“贪多求快”,今天学目标检测,明天学大模型,后天写Web服务,最后什么都只懂皮毛;二是“闭门造车”,光看教程不动手,或者整天看别人写的复盘,自己一潭死水。我的体验是,一定把“每学一个概念就用代码验证一遍”当作铁律。

还有一条很重要的经验:坚持写“实验记录文档”。我自己有个习惯了,每天结束时把当天做了什么、看到了什么现象、当前困惑什么问题,用十几行话记录下来。这个习惯在项目中期发挥的价值远超预期——它帮你在两周后还能准确回忆“当时之所以放弃某个方案,是因为验证集F1一直卡在0.83上不去,而不是因为你忘记了”。

最后再说一句心里话:如果不给“AI工程师”加太多高深滤镜,它其实和“掌握了很多成熟工具与方法的软件工程师”很像。核心区别只是对数据的处理能力与对模型的工程化掌控。这条路没有一个“终点时刻”,它更像持续在“新问题—新解法—新坑—新实践”之间打转的日常工作。你能做的最好的准备,就是让自己的每一步都建立在扎实可复现的方式上,剩下的,就交给持续积累。

RELATED READING

延伸阅读

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