不用体验,不用纠结框架选型,这一篇就是把“ai-engineering-from-scratch”这条路从头到尾趟一遍的完整记录。我自己就是从零基础一路摸过来的,踩过的坑比写过的代码多,所以这篇不是教科书,是实实在在的工程笔记。内容围绕AI工程师的核心技能、项目落地路径、模型选型与部署实战、以及日常排查技巧展开,适合刚入行想系统学习AI工程化的人,也适合已经在做但总觉得知识体系零散的同学参考。全文以经验分享为主,该给代码给代码,该讲原理讲原理,尽量让每个环节都能直接照做。
1. 先搞清楚AI工程到底是什么,再决定学什么
很多人一上来就问我“AI工程师是不是就是训练模型的”,这个理解不完整。AI工程化是把一个模型从想法变成可用产品的全过程,训练只是其中一个环节。真正的AI工程至少涉及数据、模型、部署、监控、迭代五条线,缺一条线后面都会出问题。明白这一点,你的学习路线才不会跑偏。
1.1 从零开始的完整学习路径
如果你现在是个新手,别急着把深度学习论文翻烂。先按这条路径走,节奏更稳:
- 第一阶段:Python基础 + 数据处理。Python是AI工程的第一语言,pandas、numpy这些库要熟到不用查文档。建议花2-3周把常用API过一遍。
- 第二阶段:机器学习基础。看懂sklearn,理解回归、分类、聚类、训练集/测试集划分,知道什么是过拟合。这阶段不是为了让你建模,是为了建立直觉。
- 第三阶段:深度学习框架入门。PyTorch或TensorFlow二选一,个人建议PyTorch,工程社区生态更活跃。会用DataLoader、会写训练循环、会保存和加载模型权重。
- 第四阶段:模型部署与MLOps。学会用FastAPI包接口、用Docker做镜像、用Kubernetes或单机服务跑推理,理解模型生命周期管理。
- 第五阶段:性能优化与系统设计。能处理高并发推理、模型量化、缓存策略、异构算力调度,这些才是AI工程师和算法工程师拉开差距的地方。
有人问我数学要不要学得很深。实话讲:高等数学、线性代数、概率论要补,但不必等学完再动手。学到哪补到哪,比系统啃完再上手效率高得多。我自己是先跑通了一个图像分类项目,回头再补梯度推导,反而记得更牢。
1.2 AI工程师的核心能力矩阵
学习路径是纵向的,能力矩阵是横向的。我习惯把AI工程师的核心能力分成四个象限,你可以对照自查:
技术能力包括编程能力(Python、C++/Go二选一更好)、机器学习/深度学习基础、系统设计能力(分布式的概念、消息队列、缓存、数据库)。第二象限是工程能力,包括版本管理(Git)、容器化(Docker/K8s)、CI/CD流程、监控与日志采集。第三象限是数据能力,包括SQL、特征工程、数据管道(Airflow等)、数据质量校验。第四象限是软技能,包括需求拆解、跨团队沟通、成本估算。
这四块里最容易被人忽视的是系统设计和成本估算。很多算法背景的同学只关心模型效果,上线之后QPS一上来,服务扛不住,或者GPU账单爆炸,才发现AI工程不是跑通一个notebook那么简单。面试官现在也越来越喜欢问这类问题,“你这个模型上线后单次推理成本是多少”“并发200的时候延迟会不会超时”,答不上来就很尴尬。
2. 用哪个框架、跑在什么算力上,这些选型问题一次说透
工具选型在AI工程里极其重要,选错了后面迁移成本巨大。这里只讲实用层面,不搞信仰之争。我自己的组合是PyTorch训练 + ONNX Runtime/ TensorRT推理 + FastAPI服务化,数据管道用Airflow,实验管理用MLflow。这套组合足够支撑从单机实验到中等规模生产的全部需求。
2.1 深度学习框架选择的底层逻辑
PyTorch和TensorFlow的对比吵了五年,我的判断标准很简单:看社区生态和迭代速度。PyTorch在产品迭代上一直领先,HuggingFace等主流模型库原生支持PyTorch,新论文的官方实现也大多数给PyTorch版本。工程要追新模型,PyTorch会省很多适配时间。
但有一个例外:如果是做纯服务端推理、且团队里Java或C++背景的人多,TensorFlow Serving和TFLite的部署链路可能更顺。你选框架的时候不能只考虑自己写着顺手,要考虑整个团队和后续维护的人。技术选型的问题,永远一半是技术问题,一半是组织问题。
另一个容易忽视的选型是模型表示格式。训练用PyTorch的.pt,但部署阶段我强烈建议转成ONNX。ONNX是一个中间表示格式,相当于把模型翻译成通用的“世界语”,这样你就能用不同推理引擎去跑,比如ONNX Runtime、TensorRT、OpenVINO。好处是两个:第一,推理性能通常有提升(因为推理引擎做了图优化);第二,部署时可以换成更适合目标硬件的后端,不必被训练框架绑死。
2.2 算力选择与成本控制
算力是AI工程最大的成本大头,我这里直接给一套实测过的配置思路:
训练阶段,新手起步用云GPU实例的按量付费就行,不用买卡。常见的入门配置是单卡v100或A10,显存16GB以上就能跑大多数中小模型(BERT-base、ResNet、YOLO系列都没问题)。如果做大模型微调,显存需求会跳到40GB以上,这时直接上A100或H100的实例更划算。
推理阶段算力评估我一般按这个公式毛估:
GPU显存需求 ≈ 模型参数量(以字节计) × 2(FP16)+ 中间激活值预留 ≈ 参数量(GB) × 3
举例:一个7B参数模型,FP16下权重占14GB,加上激活和缓存,至少需要40GB级别显存的显卡才能跑得舒服。不够的话就得做量化(INT8/INT4)或者模型分片,成本立刻上来了。
这里还有一个很多新人踩过的坑:你以为推理只要一张卡就够了,实际生产环境要看吞吐和时延的平衡。单张A10跑一个小模型延迟是50ms,看起来不错,但并发200的时候可能直接排队五六秒。真到这一步,你需要的是多卡负载均衡、批处理(dynamic batching)和适当的模型副本数,而不是单纯换一张更贵的卡。
成本控制上,我个人的经验预算分配大致是数据集准备和清洗占30%、训练和实验占40%、部署和监控占20%、文档和维护占10%。你要是在数据阶段省时间,后面模型反复返工,代价会翻几倍。
3. 从零手写一个完整的AI工程化项目
光说不练假把式,这里我把一个完整的AI工程化项目拆开讲——以文本分类系统为例,从需求定义到上线监控全流程走一遍。这个项目我从头做了很多遍,算是打磨过的最适合展示“AI工程全貌”的场景。
3.1 需求定义与方案设计
项目背景很简单:给一家内容平台做评论审核系统,要能自动判断一条用户评论是否包含违规内容。听起来是典型的文本二分类问题,但实际的AI工程化难点在于几条非模型层面的需求:
- 单条评论延迟必须低于300ms(用户体验要求,也是合规审核的时效要求)。
- 并发峰值预估500 QPS,且大部分请求集中在晚上8点到11点。
- 精度要求高,同时误杀率(把正常评论判成违规)要低于0.1%。
- 模型需要每周迭代一次,要能平滑上线和快速回滚。
需求拆完你就能看出来,这不仅是训练一个分类器的问题。你要设计数据回流流程、模型版本管理方案、推理服务的高并发架构、以及监控告警体系。下面每一块我们逐个解。
3.2 数据准备与特征工程
数据是一切AI项目的地基。评论审核这个场景数据来源有两部分:历史人工审核记录(有标签),以及线上用户举报后的复核结果(弱标签,噪声大)。处理流程如下:
第一步清洗。去掉重复评论、纯表情、无意义短文本(“哈哈哈哈”“沙发”等)、明显非中文乱码。这一步我用的是规则+简单模型双检,规则可以过滤掉60%的明显脏数据,剩余部分交给一个mini模型跑一遍相似度去重。
第二步打标。历史记录里直接拿人工审核的结论做标签没问题,但要注意标签的时间漂移问题——半年前的“正常评论”可能现在看是违规,因为政策规则在变。我的做法是定期抽检历史数据,抽检比例在5%左右,把不一致的标签放入“待人工复审”队列。
第三步特征工程。文本分类领域Bert、分类模型可以直接吃原始文本,但工程上仍建议加几个辅助特征,比如评论长度、URL出现次数、特殊符号密度、用户历史违规次数。这些特征对提升模型鲁棒性帮助很大,而且特征可解释性强,上线后更容易排查问题。实测下来融合特征比纯文本模型F1值能提升2到3个点。
第四步数据划分。按时间切而不是随机切——用前80%时间段的用户评论做训练,后20%做验证,这样才能模拟真实上线后的分布情况。很多新手用随机划分导致验证集和训练集同分布,上线效果暴跌,根因就在这。
3.3 模型训练与调优记录
基线模型我用的是BERT-base中文版本,因为评论属于短文本,bert的编码能力已经足够,不需要上更大的模型。训练配置参考:
学习率2e-5,batch size 32,max sequence length 128,训练3个epoch。优化器用AdamW,加weight decay 0.01。这里有个细节:文本分类任务学习率一定要用一个很小的值,因为在预训练权重基础上微调,学习率太大会破坏学到的语言表征。多试几次你会发现,无论如何都比5e-5的F1值低不少。
训练过程中记录两个关键曲线:训练集loss下降曲线和验证集准确率变化。我发现这个项目在2个epoch时验证效果最优,第三个epoch已经开始过拟合——典型特征就是训练loss还在降,验证F1不再涨。
调优环节我做了一轮类别不均衡处理。违规评论占比大约只有3%到5%,直接训练出来的模型会倾向于把大多数评论判为正常。我用Focal Loss替代标准交叉熵,以及正样本过采样的组合方案,把少数类的召回率从61%提到83%。如果两步一起做效果最好,单独用Focal Loss不过召回率65%左右。
3.4 模型部署与服务化
模型训好之后只是第一步,把它部署为一个高可用的推理服务才是工程的关键环节。我的部署步骤如下:
第一步模型导出。把PyTorch模型转成ONNX格式,同时固定动态轴(batch维度设成动态,sequence长度也设成动态)。这里有个坑:BERT模型的attention_mask如果处理不好,导出后推理结果会和原模型不一致,一定要在导出前用测试样例比对输出。
第二步推理服务封装。FastAPI写一个简单的接口,接收文本,返回类别和置信度。内部用ONNX Runtime跑推理。为了支持高并发,我加了队列和批处理逻辑:请求先进入队列,推理线程按批次聚合处理。100ms内凑到的请求合成一个batch,统一推理后再按请求拆分返回。这样单卡吞吐量提升40%左右,代价是单条请求的最大延迟有所增加,需要在业务允许范围内控一下。
第三步Docker容器化。镜像基于nvidia/cuda基础镜像,装好ONNX Runtime和FastAPI。这个容器要同时适配CPU和GPU环境,所以依赖尽量精简。镜像体积能压就压,用python:3.9-slim做基础镜像,再从源码编译ONNX Runtime反而更干净(编译时只带CPU或GPU开关),别一股脑塞一堆CUDA依赖。
第四步服务编排。生产环境我用的是Kubernetes管理副本,HPA(Horizontal Pod Autoscaler)根据CPU利用率和请求QPS自动扩缩容。推理服务是CPU密集+GPU加速的混合型负载,所以HPA指标要同时看两者,单独看CPU经常误判。另外必须配readinessProbe,接口返回健康状态,扩缩容才准确。
3.5 监控、日志与模型迭代闭环
上线不等于结束,监控才是AI工程里最花时间、也最体现水平的部分。我建立三层监控体系:
业务层监控:请求量、时延分位数(p50/p95/p99)、成功率、各分类占比。这层用Prometheus+Grafana即可,重点看p99,日常抖动可以容忍,持续恶化就必须处理。
模型性能监控:线上模型的输入数据分布变化,以及抽样人工复核的结果。这一步很多团队省略,省略之后出的事故基本都怪模型“突然变蠢了”——实际是数据分布漂移,模型没变,输入变了。
系统资源监控:GPU利用率、显存占用、CPU负载。这里有个常见误区:GPU利用率接近100%不一定是好事,如果batch特别大,单请求延迟会不可控。要平衡利用率和时延,利用率在70%到85%之间通常是比较健康的状态。
闭环迭代流程:线上抽样结果进入标注队列,每周补充训练数据,重训模型,跑离线评估,通过后走蓝绿发布上线,观察24小时关键指标,没有异常就全量切换。整套流程用Airflow做定时调度,模型版本全部记录在MLflow里。每次发布都能追溯到数据和训练参数,出问题能快速回滚到上一个稳定版本。
4. 一线实战中的高频问题与排查手记
两年多来我在不同项目里记录了一堆问题和排查过程,这里挑最有代表性的几个,每一个都是真金白银买来的教训。
4.1 线上推理结果和本地测试不一致
这是部署环节最诡异的问题。有一次更新模型后测试没问题,上线后部分请求返回结果和离线测试时完全不一样。排查下来发现是tokenizer分词的版本问题——训练时用的transformers库版本是4.18,部署环境里被依赖升级带到了4.28,分词结果悄悄变了。同一个句子,分词器不同,tokenize完的结果不同,模型输出自然不同。
从这件事之后我养成了一个铁律:tokenizer必须和模型一起固化下来,用ONNX导出的时候连同vocab一起冻结。同时部署镜像里锁死transformers的版本号,不允许用latest标签。这类问题排查起来很隐蔽,涉及NLP的一定要注意。
4.2 GPU利用率很低但延迟很高
遇到过GPU利用率只有30%,但p99延迟超过800ms的怪事。你说算力没用上,请求却在排队。最后定位到原因是推理服务里每个请求单独创建了推理会话(Inference Session),等于每个请求都要重新加载一遍模型图和权重,开销极大。
解决办法是会话复用 + 显存预分配。ONNX Runtime的session在进程内全局只创建一次,所有请求共用。优化后同样的流量GPU利用率直接到80%,延迟降回100ms以内。这类性能瓶颈很隐蔽,日志里面看不出来,必须做profile才能发现。
4.3 增量训练导致灾难性遗忘
做评论审核模型要不停吸收新样本,我一开始直接在原有权重上继续训练,结果发现新增样本虽然表现好,但老样本的准确率显著下降——典型的灾难性遗忘。这一点在NLP领域比CV更明显。
解决方案是采用经验回放策略:每次增量训练时固定抽取一定比例的历史样本混入,比例大概在20%到30%之间。这个方案简单有效,不用上太复杂的正则化手段。还有一个补充技巧:训练时把预训练层的学习率调得比新增分类头更低,通常是十分之一到百分之一,这样可以在吸收新知识的同时保住旧知识。
4.4 特征服务与模型服务解耦
特征工程里有一类特征是动态的,比如“用户历史违规次数”。一开始我图省事,在推理接口内部查询数据库实时计算,结果高并发时数据库被打爆,接口超时率飙升。
后来把特征计算拆成了一个独立的特征服务,预计算好写入Redis这类缓存,推理服务启动时加载特征快照,动态特征通过异步管道更新。API层只负责取特征拼请求,不再关心特征怎么来。这样一个简单的解耦让整体可用性从99%提升到99.9%以上。
4.5 模型版本管理与回滚
还有一个看起来不起眼但早晚要踩的坑:模型上线后想回滚,结果回滚失败。原因是当前版本的模型文件被推理服务一直持有文件句柄,无法覆盖删除,回滚操作自然失败。后来统一改用模型文件不可变策略——每个版本生成唯一的版本号目录,服务通过软链指向当前版本,回滚只需要切换软链,不涉及文件删除和覆盖。
这个思路跟生产环境镜像管理是一致的:镜像一旦构建就不可变,部署通过标签来切换版本。任何情况下都不要在运行时修改模型文件、代码文件。如果你需要热更新参数,走配置中心,别直接改文件。
5. 算力规划和成本优化的几个实用公式
最后单独讲一下算力规划,因为这是我看到最多人拍脑袋决定的部分。AI项目的成本如果控制不好,甚至可能拖垮整个项目的中期阶段。这里直接给一套我验证过的估算方法。
训练成本估算公式:
训练总算力消耗(PFLOPS·天)= 模型参数量(万亿) × 训练token数(万亿) × 6
这个6代表Transformer模型每个token前向+反向大约需要6倍参数量级别的浮点运算。举个例子,一个70亿参数模型,用200亿token训练,粗略算总消耗就是0.7万亿 × 2万亿(写错了,0.7×200亿=140亿,再乘6,实际要按单位统一来算)——换算成实际数值大概是840 PFLOPS·天级别。然后用单卡算力反推:一张A100的BF16算力约312 TFLOPS,利用率按50%算(实际训练通常达不到理论峰值),那么单卡一天产出约312×0.5×86400 = 13.5 PFLOPS。拿840除以13.5约等于62卡天,也就是说你用8卡A100训练大约需要8天左右,或者32卡需要近2天。事先用这个公式过一遍,预算申报和工期排期心里就有底了。
推理成本估算更需要注意:训练是短痛,推理是长痛。模型上线跑一年,推理成本可能会数倍于训练成本。做成本模型时要考虑峰值预留、副本冗余、灰度发布的额外资源。我的经验是推理资源按平均值1.5倍冗余预留就够,预留太高资源浪费明显,太低容易在流量高峰出问题。
成本优化的优先级我排成这样:
- 量化优先。INT8量化实测能减少近一半显存,性能损失可以控制在1%以内。4bit量化追求极限显存,但对精度影响需要评估。
- 批处理优先。能合并的请求尽量合并,吞吐量提升显著。
- 缓存优先。高频相似请求接缓存,能挡住大量重复计算。
- 最后才考虑换硬件。硬件升级是提高成本上限,而不是降低单位成本。
6. 给准备入行AI工程的人几句掏心窝的话
这篇写到这里,核心内容差不多讲完了。最后分享几个我自己带新人时反复说的经验。
第一个经验:不要贪多。很多新手同时学PyTorch、学K8s、学Kafka、学Spark,学一个月发现自己什么都会一点,什么都不会。AI工程的知识体系确实庞大,但要有主次。我的建议是先端到端跑通一个最小闭环:训练一个能用的模型、部署成一个能访问的服务。这个闭环建立了工程直觉,后面学什么都有方向。
第二个经验:多记录,少收藏。我看过太多人在GitHub收藏一堆项目、在浏览器存上百个标签页,实际上真正动手复现的没几个。收藏是学习的错觉,你真正读过的代码、真正调过的bug才会变成自己的东西。我每次项目结束都会写技术总结,写的时候才发现很多地方当时没想明白,写一遍就通透一遍。
第三个经验:敢于接脏活累活。数据清洗、写监控脚本、做部署流水线,这些活看起来不够“AI”,但恰恰是AI工程师能力的核心体现。纯算法岗位的竞争激烈程度已经很高了,能搞定端到端工程的人反而稀缺。低处下功夫,高处才有竞争力。
AI工程这条路确实没什么捷径,但也没那么玄乎。把基础打牢、把项目做深、把坑踩一遍,两年时间足够让你成为一个靠谱的AI工程师。这篇总结是写给当年刚起步的自己的,也希望能给正在这条路上的你省点时间。