news 2026/10/2 11:24:47

从零到一构建AI工程:数据、训练、部署与监控全流程实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从零到一构建AI工程:数据、训练、部署与监控全流程实战

从“收藏从未停止,行动从未开始”到真正写完一条model.predict(),我见过太多人卡在AI工程那道看不见的门槛上。ai-engineering-from-scratch这个标题看着像一份课程大纲,但真正动手去做的时候会发现,知识点散落成一百个碎片:数据要清洗,模型要调参,上线要处理延迟,回滚要保住缓存。这篇文章不打算给你铺开一张无所不包的地图,只讲我从零把一个AI项目推到生产环境时,那些必须踩实、绕不开的关键环节。适合那种已经有Python基础、跑通过几个notebook,但没完整做过一个AI工程的读者。我这里说的“工程”,指的是模型能稳定跑在服务里、数据能持续迭代、出了问题能快速定位,而不是训练完就躺在硬盘里的ipynb。

1. 先想清楚再动手:AI工程到底是什么

1.1 调包侠和AI工程师的分界线

我觉得有必要先做个界定。现在网上讨论AI的声音太杂,有人把“会调用现成API”叫AI工程,有人把“跑通一份开源代码”叫AI工程,还有人把“训练了个模型并在wandb上看了曲线”也叫AI工程。这些都不完全错,但都不足够。

AI工程的核心是让模型以稳定的服务形态持续产生价值。训练只是第一步,后面跟着数据清洗、特征工程、模型评估、接口封装、性能调优、监控告警、版本迭代这一整套链条。调包侠关心的是model.fit(X, y)能不能跑通,AI工程师关心的是这个管道放进生产环境后,面对真实流量、脏数据、资源抖动,还能不能丝滑运转。

我印象很深的一次经历:早先做文本意图识别,模型在离线测试集上准确率91%,我满心欢喜地封了个/predict接口。上线不到半天,线上传进来一堆表情符号、中英混打、拼音缩写,准确率直接掉到82%,还因为请求量上来之后Docker容器内存被撑爆,导致服务白白挂了十几分钟。那次之后我才真正意识到,“从零开始做一个AI工程”和“从零开始训练一个模型”完全是两条路。前者多出来的工作量,恰恰是工程化落地最值钱的部分。

1.2 一张从零到一的能力地图

从零开始,不是说你得先啃完三本数学书再去碰代码。我比较建议按“学以致用、以用促学”的方式,沿着一条主线走完一个小而完整的项目。能力地图大致可以分成五层:

  • 第一层:Python工程能力。我指的不是写函数,而是能组织代码、管理依赖、处理异常、写自动化脚本。至少要会用虚拟环境、会写类、会读第三方库源码的关键路径。
  • 第二层:数据工程基础。数据获取、清洗、标注、版本管理、特征存储。这层最不性感但最吃功夫,我个人的经验是永远不要低估数据问题引发故障的能力。
  • 第三层:模型训练与调优。理解损失函数、优化器、评估指标,能在合理时间内训出“足够好”的模型,不是追着SOTA跑。
  • 第四层:部署与服务化。把训练好的模型包进API、写Dockerfile、做健康检查、控制显存和CPU开销,让“能用”变成“好用”。
  • 第五层:迭代与运维。写单元测试、跑回归、做灰度、看监控、分析badcase、回滚版本,把模型当成持续演进的服务来养。

这五层并不是非要学完一层再进下一层。真实做法往往是螺旋上升:先做一个小项目,这五层各踩一脚;再做大一点的项目,加深每一层的理解;循环两三轮,你就发现自己能独立搞定一整套AI工程了。

2. 技术主线:四条线并行推进

2.1 数据工程线,卡脖子环节

from-scratch学习最容易跳过的就是数据工程,但线上事故十有八九和数据有关。数据这条线要掌握的东西我梳理下来有这么几块:

数据采集与存储。爬虫、数据库同步、日志埋点、外部数据源对接。很多新手以为数据是别人给好的csv,但真实业务里你需要面对的是脏乱差的原始日志、字段缺失的数据库、格式混乱的Excel。存储上至少要懂得区分原始数据层、清洗数据层、特征数据层,用合理的目录或表结构把它们分开,不要清洗完就丢了原始数据。

数据清洗与标注。清洗包含去重、异常值过滤、缺失值处理、格式统一。标注则是AI工程特有的环节,分类标签、实体标注、回归目标都牵涉标注规范。我强烈建议从第一步就把标注规范写成文档,哪怕你只是一个人干活。因为标注口径一变,模型性能变化会非常剧烈,没有规范你根本没法溯源是哪一批数据出了偏差。

数据版本管理。模型性能变化有时不来自代码,而来自训练数据的变更。所以数据集也需要像代码一样有版本,至少要用目录或清单文件记录“这个模型是拿哪一批数据训练的”。有条件可以上dvc或lakeFS,条件有限就规范化目录名加manifest文件,核心是任何模型都能找回它对应的数据。

数据增强与样本均衡。对深度学习模型,尤其是文本、图像任务,数据增强是提升泛化能力的性价比很高的手段。样本不均衡也很常见,比如二分类正样本只有5%,直接训练模型会偏向多数类。处理方法有欠采样、过采样、调整class weight、合成样本等,需要根据任务来选。

我给一个自己常用的清洗流程参考:先做字段级探查(每列的非空率、唯一值率、分布直方图),再做规则级清洗(去掉明显异常值、统一格式),再做人工抽检(抽样500条看清洗效果),最后生成清洗报告存档。别嫌繁琐,这个流程能拦住大量低级问题。

2.2 模型训练线,别一上来就抱大模型

现在大模型很热,很多新人想一步到位做微调,结果被显存、数据规模、损失发散折腾得头昏脑涨。我的建议是先在小规模经典模型上跑通全流程,再升级到大模型。模型训练这条线,关键的深度理解点有:

损失函数与评估指标的关系。分类任务常用交叉熵损失,但评估时看的往往是准确率、F1、AUC。损失是模型优化的目标,评估指标是业务关心的结果,两者不一致时需要额外设计,比如给少数类更高的损失权重。我把这个关系比作开车:损失是方向盘控制的具体角度,准确率是最终有没有到达目的地,不能只看方向盘而忘了看路。

过拟合和欠拟合的判别。训练损失持续下降、验证损失先降后升,这是典型过拟合;两个损失都居高不下,那大概率是欠拟合或者数据本身太难。解决方向完全不同:前者加正则、加数据增强、降模型容量、早停;后者换更强模型、加特征、多训几个epoch。

训练稳定性。我见过太多新手loss直接飙到nan,其实排查方向就那么几个:学习率过大、数据里有异常值、优化器状态问题、数值稳定性处理缺失。建议训练脚本里固定随机种子,便于复现和定位问题。

迁移学习与微调。对于视觉任务,先加载ImageNet预训练权重做微调,通常比从头训练收敛更快、效果更好。对于文本任务,直接使用预训练语言模型做分类特征提取也是常规操作。但这里有个经验:微调的学习率要调低,加载预训练权重后,全量参数用1e-5到5e-5比较稳,随机初始化的新层可以稍微高一点。

2.3 推理与部署线,模型能跑和能用是两回事

模型训练完只是开头,部署上线需要的东西完全是另一套知识。这条线最容易踩坑,也最能体现工程能力。

离线预测 vs 在线服务。离线预测对延迟不敏感,可以跑批处理;在线服务要求低延迟、高吞吐。我建议从在线服务做起,因为挑战更多、收获也更多。在线服务的技术栈至少包含:FastAPI或Flask写HTTP接口、Docker做环境隔离、Gunicorn或Uvicorn做并发管理、健康检查端点、超时控制。

模型体积与服务性能。一个500MB的深度学习模型直接加载进内存,每个请求都过一遍全量计算,就算GPU也得算一会儿。这里需要掌握模型量化(fp16、int8)、批处理(等待一小批请求一起推理)、模型裁剪(减小输入尺寸、删减层数)等优化手段。我的经验是先量化后优化代码,量化通常能带来30%-50%的加速和显存下降,改动量很小。

GPU使用注意。GPU显存比内存更金贵。上线前要算清楚并发和显存的关系,一个进程占用多大显存、多少个worker共享一张卡,都需要实测。还容易忽略的是GPU的冷启动时间和CUDA上下文切换开销,批量预测时要把这些算进吞吐模型里。

CUDA/CPU兼容与多环境一致性。训练环境有GPU,生产环境可能没有。训练时用fp16加速,但推理服务器CPU只支持fp32,这就可能导致推理结果和测试不一致。解决办法是部署前在目标环境上跑一遍模型的确定性验证,把输出误差控制在可接受范围内。

2.4 评估与迭代线,让模型可度量

这条线最容易被忽略,但离线评估没做扎实,线上出了问题才发现,代价会特别大。评估线要做的事情:

离线评估集设计。训练集、验证集、测试集要划分清楚。测试集必须模拟真实分布,而不是随机切分出来的“温室数据”。比如时间序列任务要按时间切分,防止未来数据泄漏到训练集里。用户产生的数据往往长尾效应严重,测试集里除了随机样本,最好再单独放一些边界样本(极端长度文本、低清晰度图片、罕见类别)。

上线前的backtest与跟跑。模型要上线,先拿历史数据回放一遍,看它的预测结果和真实结果差异。如果有条件,做一段时间的影子模式(shadow mode),让新模型和旧模型同时跑,但不直接返回新模型的预测结果,只在后台记录差异。这样能极其有效地发现离线评估看不到的问题,比如新模型在某种用户群体上表现异常。

线上监控指标。上线后要监控的不只是CPU和内存,更重要的是预测分布漂移、请求量变化、反馈数据(用户点击、好评差评、人工复核结果)。最简单的方式是记录预测概率的均值、标准差,如果今天和昨天差的太多,那大概率是数据分布变了或者上游系统有问题。

迭代闭环。AI工程不是训练一次就结束,模型需要定期用新数据重训。这个重训流程要尽量自动化:定时或事件触发、数据版本快照、自动评估、达标就发版。我见过半自动化的方式也很好:脚本把重训跑完,卡在评估环节,人看报告点通过,然后再自动部署。与其一步到位做全自动,不如先把半自动跑稳。

3. 用一座里程碑式项目串起所有技能

3.1 项目选择原则,任务闭环+数据私有

如果只看教程不亲自做一个完整项目,学到的东西永远停留在知识点层面。我推荐的项目要满足两个原则:

任务闭环。不是只做训练,而是从数据采集一直做到部署上线,期间包含数据清洗、模型训练、评估、服务封装、容器化、监控,这样每个环节都会逼你面对真实问题。比如文本情感分类,小到可以一人完成,但每个环节都不缺。我建议第一次做项目选这种规模适中的任务,不要一上来就做多模态大模型。

数据私有。项目的数据最好是你自己采集或业务真实产生的,不要直接下载一份kaggle现成数据。因为只有数据是“脏”的时候,你才能理解清洗的价值。比如你可以从应用商店评论、社交媒体公开信息里自己攒一份文本数据,或者自己拍、自己标一份小规模图片数据集,过程中的问题远比你想象的丰富。

3.2 实操步骤拆解,从数据到服务的全过程

我用一个“中文评论情感分类”项目为例,完整走一遍从零到一的步骤,每一步我尽量写得具体,方便直接参考:

第一阶段:数据准备

  1. 确定数据来源:抓取应用商店的用户评论,选2-3个分类,目标攒到1万条以上的文本。
  2. 原始数据清洗:去掉重复评论、纯标点文本、长度小于2的文本;统一全半角;压缩连续空格和换行。
  3. 标注:按正面、负面、中性三分类人工标注。抽5000条做初始标注,不够的部分后续再补。写一份标注规范,把边界情况说清楚(比如“还行”算中性还是正面、“太贵了但好用”怎么处理)。
  4. 数据版本:建立data/目录,下分raw/、clean/、label/、feat/四层;每版数据跑完后写manifest.jsonl记录文件路径、记录条数、清洗脚本版本和标注时间。

第二阶段:模型训练

  1. 特征化:先用jieba分词加TF-IDF,再切换到预训练模型BERT提取特征,两组作为对比基线。
  2. 模型选择:第一版用一个简单的线性分类器加TF-IDF,在约2000条数据上跑通;效率高、可解释。数据达到8000条以上后,再用BERT微调。
  3. 训练参数:学习率2e-5,batch size16,epoch3,优化器用AdamW,固定随机种子42。早停规则设定为验证集F1连续3个epoch不提升就停止。
  4. 评估矩阵:不看单一准确率,重点看三个类别各自的准确率和召回率,输出混淆矩阵。如果中性类被严重误判,需要追加规则或调整损失权重。

第三阶段:服务封装

  1. 训练好的模型导出成可加载的格式,这里我推荐把所有预处理逻辑(分词、清洗、标签映射)一起打进模型包里,避免接口侧重复实现,少一份逻辑就少一个bug来源。
  2. 用FastAPI写一个推理服务,包含/predict和/health两个端点。/predict接收JSON文本,内部走清洗、特征化、推理、返回标签和置信度。/health返回进程和模型的存活状态。
  3. 写Dockerfile:基础镜像选python:3.10-slim,先装依赖再拷代码,模型文件用.dockerignore排除掉,通过挂载目录传入容器。这样镜像小、构建快、模型更新不用重新构建镜像。
  4. 本地起容器,用curl发几个测试请求确认输入输出;再用locust或wrk做简单的压测,确认单worker的QPS和延迟。

第四阶段:上线与监控

  1. 服务器上用docker-compose起服务,暴露80端口;加一层nginx做反向代理。
  2. 监控指标:请求量、平均延迟、P99延迟、模型预测概率分布。预测概率分布用日志记录,每天跑个脚本统计均值、方差,和前一天对比。
  3. 告警规则:P99超过2秒告警、平均置信度连续下降超过10%告警、请求量突降告警(可能服务挂了,也可能上游出问题)。
  4. 模型更新:新模型和旧模型并行跑,差异通过日志对比,观察一周再切流量。

3.3 基础设施选型,够用就好

很多教程一上来就推Kubernetes、全链路监控、特征平台,给人一种“不上云原生就不算工程”的错觉。我做过的项目里,中小规模的AI应用,一套docker-compose足矣。我建议新人把有限的精力花在这些工具上:

  • 虚拟环境与依赖管理:uv或conda,加requirements.txt固化版本。别裸装包,几个月后环境坏了都不知道怎么修。
  • 开发调试:Jupyter用来做分析和可视化没问题,但正式代码写进.py脚本,用argparse控制参数。这样便于自动化、便于版本管理、便于别人接手。
  • 版本管理:Git是底线。模型文件不进Git,用dvc或网盘加清单管理;数据集同理。
  • CI/CD:第一版不用上完整CI,先写一个Makefile,把lint、test、train、deploy几个命令固化下来,实现“专人专机一键发布”,比搭了又没人维护的Jenkins实在。
  • 监控:不追求上专业监控平台,先把日志打全,用日志文件或SQLite记录核心指标,每天看一遍。等你有明确痛点了再引入Prometheus+Grafana也不迟。

4. 进度规划与常见问题排查

4.1 三个月路线图参考

我见过太多人规划一年,结果一个月就放弃了。规划要颗粒度小、反馈快。以下是我根据带人经验整理的核心ABL路线,总共三个月,每周大约需要投入12~15小时:

  • 第1个月:基础素养与第一个微型项目前两周重点补Python工程能力和深度学习基础,会写类、会管理依赖、能理解训练循环里每个张量的维度变化。后两周做一个微型项目,比如用公开数据集训练一个十分类模型,封成FastAPI接口,跑通Docker部署。这个阶段重点是“跑通整个链路”,模型精度低没关系,链路完整比精度重要。

  • 第2个月:数据工程与经典模型深入开始自己采集和标注一份数据,按3.2节的项目流程走一遍。训练模型时手动调几组学习率和batch size,记录每组参数对应的收敛曲线和测试指标,形成自己的调参直觉。同时把评估指标从“准确率”扩展成“混淆矩阵+分指标”,理解长尾类别带来的问题。

  • 第3个月:一个完整项目+部署优化把第2个月做出来的模型推进到生产环境。这个阶段要交付的东西包括:可复现的训练脚本(README里写清楚怎么跑)、Docker镜像和部署文档、一套基础监控脚本、一份线上问题复盘记录。试试模型量化、批处理优化,压测后对比优化前后的延迟和吞吐指标。

时间规划最忌讳求大求全。如果你现在连Python的类和方法都还不太熟练,我建议前两周重心全放在写代码上,不要急着碰框架。反过来,如果你已经把notebook玩得很溜,只是没有工程化经验,前两周可以直接跳到数据工程和项目设计。

4.2 高频问题与排查技巧

问题1:训练loss不下降或直接变nan

  • 排查思路:先看数据标准化是否做对,特征里有没有异常大/异常小的值;再看学习率,1e-3以上的学习率配合小batch经常导致发散;最后看模型架构,比如激活函数在不该用的地方用了softmax做隐藏层,梯度会变得极其平滑。
  • 小技巧:给训练脚本加一个“每次迭代打印loss和梯度范数”的开关,定位发散时刻能省很多时间。

问题2:GPU显存OOM

  • 排查思路:看是不是batch size太大,把batch减半试一次;看是不是模型里缓存了中间张量,用torch.no_grad()包住推理过程;看多个加载的模型是不是同时常驻显存。我见过一个情况,两个worker各自加载一份同样的模型,显存直接翻倍,后来改成共享加载才解决。
  • 实测经验:把num_workers调低、pin_memory打开,OOM概率会明显下降。显存不够时优先降低batch size,不要急着换更小的模型,先确认代码里有没有显存泄漏。

问题3:模型在离线测试集上很好,线上效果一塌糊涂

  • 排查思路:第一看数据分布漂移,线上真实输入和训练集分布差异多大;第二看特征一致性,训练时用的特征预处理逻辑和生产环境是否完全一致;第三看延迟/并发带来的隐性影响,比如超时导致部分长文本请求直接被丢弃。
  • 核心教训:上线前一定要记录训练集的输入分布快照(文本长度、数值范围、类别分布),上线后持续和快照对比,漂移超过阈值就要告警。

问题4:服务接口能用,但一压测就502/超时

  • 排查思路:看同步阻塞堵住了事件循环;看线程池/进程模型配置不合理;看有没有外部依赖拖慢响应,比如每次请求都会查数据库或调用别的http服务。
  • 处理方案:在线推理尽量模型预加载、特征预处理结果缓存、同步IO放到线程池中。也可以用gunicorn多worker + 异步框架混搭的模式,先满足业务需求再优化架构。

问题5:标注不一致导致模型学偏

  • 排查思路:拿同一条数据人工复标3次,看不同标注结果占比;把标注规范对不上的边界case单独收集起来,开会定标准。
  • 规避方法:标注阶段留出5%的重复标注数据,用来计算标注一致性(比如用Cohen's Kappa)。一致性过低时先别训练,把规范和样本重新对齐。

4.3 我的几条独家避坑心得

这些心得不是一个晚上想出来的,都是真金白银踩出来的。

第一条,把Write documentation当成工程进度的一部分。哪怕只给你自己看,也要在项目里写清楚“数据在哪、模型怎么训、服务怎么起”。我见过一个项目,三个月后原作者自己都说不清训练数据版本,更别提别人接手。写一份一页纸的README,关键时刻能救你一命。

第二条,一切以自动化为目标。手动跑训练、手动传文件、手动重启服务,这些阶段性的“手工活”会在项目规模变大后变成大坑。哪怕用最简单的Makefile或Shell脚本固化下来,也比纯手工操作强十倍。我习惯是每个操作步骤都有一个可重复执行的命令,配合echo打印关键状态,跑起来就知道卡在哪一步。

第三条,把“失败”当成设计的一部分。工程里说的健壮性不是在线代码里try-except到处吞异常,而是预判失败路径:输入格式不合法怎么处理、依赖服务挂了怎么降级、模型推理超时怎么返回兜底结果。这些路径测试覆盖住,线上才能睡得安稳。

第四条,模型可复现性优先于模型精度。追求一个高精度但复现不了的模型,在工程上没有意义。每次实验记录下数据版本、代码commit、训练参数、随机种子,这是AI工程的基本素养。精度以后可以慢慢调,复现不了连调的机会都没有。

5. 踩过的坑和想明白的事

这一节算是我个人真正的复盘沉淀,说几个最值得琢磨的。

坑之一:以为模型是项目中唯一重要的部分。我头几次做项目时,80%的精力都放在模型结构上,数据就是简单处理一下。后来线上故障复盘时发现,大部分问题都出在数据预处理和生产环境不一致上。占比上可能是模型占20%,数据占30%,工程架构占30%,其余占20%。想明白这个之后,我调整了精力分配,项目的稳定性提升了很大一截。

坑之二:把深度学习框架当玩具。早期用PyTorch就是model(x)编个循环,内部机制半懂不懂。直到一次模型部署后发现训练和推理结果对不上,排查到model.eval()没有调用、Dropout还在生效,才意识到框架内部状态管理也是工程的一部分。类似的有requires_grad、no_grad、inference_mode的适用场景,都值得认真读一遍文档,不要凭感觉。

坑之三:低估线上运维的工作量。第一次部署模型时,以为服务上去就完事,结果半夜被告警吵醒,发现是上游接口变动导致请求格式错误,模型还在正常运行但输入全乱。那次之后我才养成了“先监控、后放手”的习惯,新服务至少盯一周的预测分布和错误日志,稳定下来再考虑减少关注。

想明白的事:AI工程的核心其实是“可控”。数据可控、模型可控、部署可控、回滚可控。这四个“可控”做到了,AI系统才谈得上稳定和可靠。训练过程再炫酷,控制不了也只是实验室里的花样。

从零开始做AI工程,从来没有一条笔直的大道。最好的路径其实就是老老实实做一两个完整项目,把数据、训练、部署、监控从头到尾走几遍,踩过的坑自然会变成你的经验。我目前也在持续把一些训练日志、监控脚本和小的实验记录整理成模板,后续如果这类内容大家觉得有用,我会继续拆解如何做模型重训的自动化、低成本监控告警方案,还有更复杂的多模型A/B测试场景。以上算是我个人在新手期摸爬滚打后的沉淀,供准备入坑或正在入坑的各位参考,希望少走弯路。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/2 11:22:42

嵌入式内存管理实战:从内存池到栈溢出,把每一字节花明白

干嵌入式这行,谁没被内存折磨过几回?我印象最深的一次,是给一个跑着RTOS的工业控制器排查问题,设备运行两三天就死机,复位后又能撑一阵。查了几周的业务逻辑愣是没发现毛病,最后用内存统计一查,…

作者头像 李华
网站建设 2026/10/2 11:22:34

告别GUI:用Lua脚本打造J-Link RTT命令行自动化调试工具

1. 为什么我要自己写一个 RTT 命令行工具嵌入式调试这件事,做过几年的人都有一个共同感受:IDE 里的调试器很好用,但一旦离开 IDE,事情就变得别扭起来。J-Link RTT 就是典型例子。SEGGER 官方的 RTT Viewer 是个 GUI 工具&#xff…

作者头像 李华
网站建设 2026/10/2 11:21:57

PyCharm 中文配置指南:解释器、venv、镜像源与远程开发实战

简介:这是一份系统讲解 PyCharm 使用技巧的中文电子手册,整理自资深云计算博主的实战总结,面向 Python 初学者和希望提升 IDE 效率的中级开发者。内容从版本选择与下载安装起步,依次讲解社区版、专业版、教育版的功能差异&#xf…

作者头像 李华
网站建设 2026/10/2 11:21:17

穿越系统迷雾:揭秘 Cursor 提示词的奥秘与 TaoToken 统一 Key 配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/2 11:20:57

Promise执行机制全面解析:状态、微任务与并发控制

关于Promise的执行机制,面试考得最多,但实际开发里真正弄明白的人并不多。很多前端拿得出手“三种状态”“宏任务微任务”这些词,真到了排查问题时,却连 uncaught (in promise) 的报错从哪冒出来的都说不清楚。 这篇文章我准备…

作者头像 李华