1. 内容整体设计与思路拆解
1.1 先搞清楚"AI工程"和"单纯写模型"的区别
去年年初我开始接触这个标题对应的方向时,一度陷入一个很典型的误区——天天刷论文、复现模型、调参玩,觉得把准确率从 92% 刷到 93% 就是"做 AI"了。后来被拉进一个真实项目才发现,模型训练只占整个系统的一小块,真正的工程问题全在模型之外:数据从哪来、格式怎么定、训练好的模型怎么给业务调用、线上效果掉了怎么及时发现、推理成本谁来控。这时候我才意识到,所谓的"ai-engineering-from-scratch",核心不是从零实现一个 Transformer,而是从零搭起一条完整的 AI 应用生产线。
如果你也是刚入门,可以参考我当时的思路:把这个方向拆成六个环节——目标定义、数据和特征、模型选型与训练、评估体系、工程交付、监控迭代。六个环节串起来才叫 AI 工程,少任何一个都只能算"交付了一个模型文件"。这篇文章就按这条链路往下走,每段都会附上我自己实测过的方案和踩过的坑,适合那种"不想只当调包侠"的数字产品经理、独立开发者、以及刚带队的初级技术负责人参考。
1.2 为什么非要从零开始做一遍
市面上现成的框架太多了,HuggingFace 上随便下个预训练模型,几行代码就能跑通一个 Demo。那年我第一版的"AI 助手"就是 flask 套了个人 API,两小时搞定,当时还觉得自己效率惊人。但真正进入生产环境就发现,Demo 的每一次成功都是侥幸——依赖版本锁得死死的,数据格式稍微变一点就崩,连个日志都没有,出事只能靠猜。
从我自己的体会出发,从零做一遍最大的价值在于把系统黑盒变成白盒。你自己写数据处理管线、自己设计评估集、自己配置监控告警,以后任何一个环节出问题,你能直接定位到是哪一天改了哪段逻辑、哪类数据的分布发生了漂移。别人给的东西,出了问题你只能祈祷;自己搭的东西,出了问题你能处置。这种掌控感,对 AI 项目的长期维护来说比什么都重要。
当然,"从零"不意味着什么都要重写一遍数学公式。我理解的是:核心链路你自己串,底层的重型计算让成熟库来扛。比如反向传播用框架的自动微分就行,但数据配比、采样策略、评估口径这些决定项目生死的东西,必须自己亲手设计。这才是工程的含金量。
2. 项目目标定义与里程碑规划
2.1 先定义"什么叫做成",再动手写代码
我见过太多项目死在第一个月,根子不在技术,在于一开始就没想清楚目标。做 AI 工程和做传统软件最大的差异是:传统软件需求清楚,写就完了;AI 项目需求天生模糊,你又不能上来就问老板"准确率要多高"——因为准确率本身就不是一个业务指标。
我习惯在第一周拉着业务方一起做三件事:第一,把业务问题翻译成预测问题,比如智能客服的诉求是"减少人工介入",那预测目标是"这个对话需不需要人工接管";第二,定义清楚正样本和负样本,坏数据比缺数据更可怕,一个标注错的正样本能带偏整个模型的判断;第三,定出"上线及格线",比如说接管的准确率达到 85%,同时人工复核的成本降低 30%,不是追求 100%,因为 AI 项目的边际收益通常不是线性的,盲目追高往往把成本翻好几倍、收益只涨一两个点。
目标定完,我会把项目拆成三个里程碑。第一个里程碑叫"端到端能跑通",哪怕效果惨不忍睹,但数据能灌进去、模型能训练、接口能返回结构化的预测结果,最多花两周;第二个里程碑叫"满意且稳定",核心指标达到及格线,并且连续一周波动在可接受范围内,通常要一个月;第三个里程碑叫"可交付可维护",补上监控、日志、回滚机制和模型更新的标准流程,这个阶段可能再花两三周。我见过最快的团队把这三个里程碑压到六周,但前提是数据质量一开始就很好,这个前置条件不可轻易复制。
2.2 资源规划:算力、人力与时间,哪个最贵
算力规划这件事,我的经验是用"实验次数 × 单次成本"来估算,而不是看峰值的机器规格。第一个里程碑阶段,我用单卡就能满足大多数中小规模的需求;但进入调优阶段以后,并行跑实验的需求上来了,我通常配置一个四卡的小集群,因为串行调参的等待时间成本往往比租机器的成本高得多。
人力分配上,我的优先级是数据工程师最贵,其次是做评估和数据分析的人,模型训练反而是门槛最低的一环。现在开源社区太成熟了,真正卡住进度的往往是"数据标注标准不统一,导致返工三周"这类数据问题,而不是模型收敛不了。时间规划上一定要预留 15% 的缓冲,不要排满。整个链路里代码出 bug 都能查,但数据标注错了往往要等业务方重新确认,这种依赖外部反馈的环节,时间不可控,排期一定要留余量。
有个特别容易踩的坑,就是想一步到位买最好的机器。其实第一个里程碑阶段,哪怕是几年前的旧卡也够跑数据预处理和基线模型,等确定模型规模再投入更高规格的资源也不迟。我第一年做项目时直接上了新卡,后来发现大部分时间 GPU 利用率不到 20%,而这个钱本可以省下来去多标几千条高质量样本。
3. 数据工程的从零搭建
3.1 数据采集与清洗:把"垃圾进垃圾出"这条铁律刻在脑子里
数据质量是决定 AI 工程上下限的头号因素,我自己在这上面的教训就值三次大坑。第一版项目从网上爬了一堆数据,没做去重就喂进去训练,结果验证集里跟训练集高度重合,看起来准确率 97%,一上线立刻被打回原形。后来重新严格按哈希值去重,才看到真实水平大概在 88%。所以做数据工程的第一件事:先建去重机制,再谈建模。
采集阶段至少要问自己三个问题:数据量够不够覆盖边界情况,正负样本比例会不会失衡,样本的时效性是否符合业务现状。我会针对每个问题写对应的校验脚本,比如统计类别分布、检测时间戳异常、识别字段缺失比例。当年写的第一版脚本,会自动把空值全填成"未知",结果模型把"未知"学成了一个有效类别,上线后一堆异常输入全命中这个类别,排查了半天才发现是填充策略埋的雷。
清洗环节我的做法是分层处理:格式层清洗负责统一编码、去掉乱码和控制字符;语义层清洗负责识别无效信息,比如重复文本、无意义语气词;一致性层清洗负责正则化时间、金额、地点这些实体表达。这三层清洗直接决定模型特征的质量,值得投入比建模多一倍的时间。
3.2 标注方案的避坑指南
标注环节是数据工程里最容易失控的,最大的坑是标准写得不够具体。我第一版标注文档说"判断该评论是否包含消极情绪",结果三个标注员给出的标签一致性只有 65%。后来我把标准改成"评论中出现负面情感词汇、消极体验描述或明确差评倾向时标记为消极,若同时存在积极与消极内容,以主要情绪倾向为准",一致性立刻提到了 88%。
另一个坑是标注数据分布被刻意"均分"了。当时质检的时候发现标注员很"聪明"地认为正反两类各标 50% 才算合格,结果样本分布完全偏离自然规律,训练出来后模型判断天然偏向均衡。解决方式是硬性要求标注员按原始顺序处理,不允许挑着标,并在后台统计每人的正负比例,偏离超过 15% 就人工介入复核。
如果你预算有限,也可以先把规则代码写出来做粗标,再由人去修正机器判断错误的样本。实践下来,这种"预标注+人工修正"的模式比纯人工标注快 40%,而且质量并不差。但前提是你的预标注规则足够准,低于 70% 准确率时,人看机器的错误标注反而会产生"锚定效应",导致标注质量更差,这一点要特别注意。
3.3 特征工程:让模型站在数据之上
特征工程近年的口碑有点两极分化,有人说深度学习时代不需要特征工程了,我的实战感受是:需要,但需要的方式变了。以前是手动构造大量离散特征给 LR 用,现在更多是设计"信息通路",把原始数据组织成模型更容易学习的形式。
我实践中收益最高的三类特征处理是:第一,文本数据做长度截断和分段,而不是整篇塞进去,超出窗口的尾部信息往往含噪,截断后效果反而更稳;第二,时间特征做周期切分,比如拆出小时、星期、是否节假日,而不是直接丢一个时间戳;第三,ID 类特征不做 target encoding 的话就不用处理,做了反而容易过拟合。
实操中还要注意特征穿越问题。比如用整个样本集统计的均值去填缺失值,会把未来信息带到训练集里,验证时指标虚高,上线就崩。正确做法是只用训练集的统计量做填充,并把这个统计量序列化保存,线上推理时加载同一个统计量。当年我被这个问题坑过一次之后,所有特征处理函数都强制拆成 fit 和 transform 两步,训练和推理共用同一套逻辑,再也没出过类似事故。
4. 模型选型与基线建立
4.1 选型原则:先让复杂的系统简单跑起来
选模型的时候,我见过两类人各踩一边:一类是无脑上最前沿的大模型,一个亿级参数的模型塞进一个小业务里,推理延迟根本扛不住;另一类是畏手畏脚,总想着先把所有数据处理完美再开始建模。正确的做法是先选一个最鲁棒的方案,把整套链路跑通,建立一个"不太好看但是真实"的基线,之后的所有改进都拿这个基线来对比收益。
具体的选型逻辑可以按数据形态来走。数据是纯文本,中小规模场景可以直接用预训练语言模型做微调;如果是表格数据为主,树模型往往是性价比之王,实测在很多结构化数据上,它对特征尺度不敏感、调参成本低,稳定性也远超玄学好调的神经网络;如果文本加结构化混合,则先分别建模再做融合。我的原则是:可解释性要求高就选简单模型,纯效果导向才考虑大模型,不要为了技术新鲜感增加运维成本。
4.2 基线模型的建立与记录规范
基线模型的设计目标不是"效果最好",而是"流程正确、指标可复现"。我在第一个里程碑通常会用一套默认参数直接跑,正则系数设置居中,学习率设置适中偏保守,训练轮数固定,不做花式调整,保证任何时间重跑都能得到几乎一样的结果。
关键的细节是实验记录规范。我吃过太大亏了,最开始调参时靠记忆,结果过了两天就忘了哪个参数配哪组指标,后来不得不重跑实验。现在我会给每个实验建一个固定格式的记录:数据版本、特征代码版本、模型配置、训练耗时、评估指标、线上推理耗时以及备注。有这套记录之后,回溯任何一个线上问题,都能很快对应到当时的实验版本。
基线实验跑通过之后,我建议大家顺手做一个"该模型的错误分析",把模型预测错的样本单独拉出来看,分门别类统计。这个工作看起来朴素,但对下一步调优的方向决策作用巨大——你会清楚地知道是缺数据、特征不合理、标注错误还是模型容量不够。我见过一个项目,准确率卡在 90% 上不去,做完错误分析发现将近一半的错判来自同一种少见样本,补了几百条数据后直接涨了两个点。
4.3 常用训练参数的"抄作业"配置
开始调模型之前,给一组我实际验证过的、在不同场景下都比较稳的初始参数。文本分类场景,学习率建议 2e-5 到 5e-5,batch size 在 16 到 32 之间,训练轮数不要太贪,除了监控损失,我还会盯验证集的每轮指标,一旦连续几轮不涨就停掉,节省大量时间。表格类任务用树模型,重点是限制树的深度和叶节点数,以及特征采样比例,这些参数控制的是模型的复杂度,比盲目加大迭代轮数收益更大。
还有个容易困扰新手的点:要不要做数据增强。我的经验是数据增强只能解决"数据多样性不足"的问题,不能解决"标签噪声大"的问题。如果标注本身不可靠,加再多增强反而是强化错误。另外,任何数据增强手段都必须只在训练集上做,验证集和测试集要保持原始分布,否则评估结果虚高,上线必现原形。
5. 评估体系的设计与效果调优
5.1 评估指标别只看准确率,要结合业务代价
准确率是最直观的指标,但绝不是唯一应该看的。当正负样本比例失调时,一个什么都不预测的模型也能有很高的准确率,误导性非常强。真正做项目时,我会先和业务方确定两类错误的代价:把普通用户误判为高风险带来的打扰成本,和把真正高风险放过带来的漏判成本。这两者往往差着一个数量级,决定了模型调优的方向。
举例来说,去年做一个内容审核辅助工具,正样本比例只有 3%。只看准确率的话,模型全判负也有 97%,但业务真正需要的是在误伤尽量少的情况下召回更多的正样本。这种场景下我会直接看召回率、精确率、F1 这三件套,并且明确我认可的"最优阈值"是偏向召回还是偏向精确。训练时模型输出的通常是概率,上线时通过调整阈值来控制判决策略,这个阈值的选择应该基于验证集上"误报代价与漏报代价"的权衡,不能拍脑袋。
5.2 过拟合的早期信号与纠偏策略
训练初期,损失值快速下降是好事,但如果训练损失持续下降的同时验证损失开始回升,那就是过拟合的典型信号,此时停手是最明智的。我常用的正则手段按优先级排序依次是:增加数据(效果最直接)、降低模型复杂度、加大正则强度、做早停、做交叉验证。
早期的一个项目里,我的训练集和验证集划分没做分层采样,导致验证集全是一个类别的数据分布,看起来像过拟合,实际上是数据划分不均匀。正确的做法是分类任务做分层采样,确保训练和验证集里各类别比例与整体一致;如果涉及时间序列特性,还得保证验证集在时间上晚于训练集,模拟真实线上场景。判断一个指标波动到底是因为模型问题还是数据问题,我用的快捷方法是看同一份验证集多次评估的波动范围,如果波动本身就很大,说明评估集规模太少或分布不稳定,先解决评估可靠性再谈调参。
5.3 利用可视化工具快速定位问题
很多新手习惯只看最终指标数值,很少画曲线。但实际上,训练曲线的形状能透露大量信息:训练损失和验证损失之间的距离就是过拟合的直观度量;曲线长时间不下降说明学习率可能太小;一步正常一步飙升,多半是 batch size 太小或学习率太大;验证曲线剧烈震荡,则需要检查验证集是否稳定、有没有对验证集做过数据增强。
训练结束后,我还会做一次特征重要度的排序分析。这一步在树模型上有现成 API 可以输出,在神经网络模型上则可以用更持久的置换特征法。拿到的排序不是用来决定上线与否的,而是帮助自己理解模型在靠什么信号做判断,失去业务合理性的重要特征,就说明数据清洗有严重问题。这个视角太关键了,因为工程交付的模型不仅是代码和权重,更是业务侧能理解的决策逻辑。
6. 工程化部署与线上稳定运行
6.1 模型部署形态的选型
模型训练完成只是中点,真正的工程挑战在部署环节。部署形态基本三种:批处理预测、实时 API 服务、嵌入式推理。批处理适合离线跑分场景,比如每日定时给用户列表打分,做一次全量计算然后存入数据库;实时 API 适合延迟敏感的场景,比如对话审核、实时推荐;嵌入式推理则适合端侧或离线环境,比如手机端应用、边缘盒子。选型的核心评估维度是延迟、吞吐和更新频率需求。
我的建议是:能用批处理解决的不要上实时服务。实时服务意味着你必须处理高并发、限流、熔断、模型热加载、监控告警,这些基础设施的成本往往是模型本身的好几倍。如果业务场景允许延迟几分钟,先把批处理跑起来,观察线上效果确认有价值之后,再花资源上实时服务,这个节奏最稳妥。
对于必须上实时服务的场景,我给一个基础技术栈组合参考:推理框架选 ONNX Runtime,比原始框架的推理性能高不少,而且不绑定训练框架;服务层用官方长期维护的异步框架,配合 gunicorn 等多进程部署;模型热加载用文件监听触发版本发布,避免每次升级都要重启服务。我的第一版线上服务就吃了"每次模型更新要停机 5 分钟"的亏,后来改成热加载方案,模型更新不停服,秒级生效,体验完全不一样。
6.2 特征一致性:线上和训练必须完全对齐
部署时最容易出的事故,就是训练时的特征处理逻辑跟线上不一致。我以前做文本特征时,训练代码里有个"去特殊符号"的正则,但线上的预处理代码是另一个人写的,少处理了一个符号类型,上线后这部分样本的特征分布直接变了,预测结果一塌糊涂。后来我规定:特征处理的代码必须打包成同一个模块,训练时导入这个模块处理数据,上线服务也导入同一个模块处理请求,从源头上杜绝分叉。
特征一致性检查还有一层:特征缺失时的默认值。训练时缺失值用均值填充,线上缺失时也要用同一个均值,不能直接用 0 填充,否则模型拿到的分布完全不同。我建议在服务里写一个单元测试,拿训练集的样本跑一遍线上特征处理,然后对比特征输出是否一致,不一致立刻报警。这个测试虽然简单,但在我的项目里拦住过三次因重构代码导致的事故。
6.3 模型监控与告警配置
模型上线后并不代表任务结束,恰恰相反,持续维护的挑战才刚刚开始。模型监控要做三层:第一层是服务监控,看延迟、错误率、QPS,这是传统运维那套;第二层是特征监控,比对线上输入特征的分布和训练时是否有漂移;第三层是业务效果监控,看模型实际产出带来的业务指标变化,比如审核率、通过率、用户反馈率。
特征漂移的检测最简单有效的方式是定期按天统计线上特征的关键百分位,和训练基线做对比,偏差超过阈值就触发告警。业务效果监控则需要定一个可量化指标,例如推荐系统的点击率、审核系统的误报率,这类指标能直接反映模型是否仍然适应当前环境。第三个容易被忽略的指标是"无预测占比",也就是模型输出的置信度极低或直接失败的比例,这个比例异常爬升往往意味着遇到了分布外的新数据,需要及时补充样本或触发再训练流程。
7. 常见问题与排障经验
7.1 训练不收敛排查顺序
训练不收敛时的排查顺序比排查方法本身更重要,乱试参数只会浪费大量时间。我按以下顺序排查:第一步检查数据管道,确认喂进模型的张量形状对不对、标签有没有错位,我遇到过大约 30% 的训练异常是数据管道 bug;第二步检查损失函数,看是不是用错了损失函数的变体,或者标签类型和损失函数不匹配;第三步检查优化器参数,学习率过大是最常见的不收敛元凶;第四步才考虑模型结构,看初始化、归一化层、残差连接这些结构性问题。
有个实际的坑值得单独说:多分类任务用交叉熵损失时,如果标签从 1 开始而不是从 0 开始,模型会一直学不正,损失高居不下。这类小细节定位起来特别费劲,因为代码逻辑看起来完全没问题。后来我会在每次训练启动时打印一小批输入和标签的样例,肉眼核对一遍再开长训练,这个习惯帮我节省了大量试错时间。
7.2 线上效果不如测试的 3 个常见原因
线上效果与测试集效果差距大,问题通常逃不出三处。一是训练测试分布不一致,测试集没能代表真实线上数据的分布,这属于数据采集时的覆盖面问题;二是特征不一致,就是第四节讲的训练线上特征逻辑没对齐;三是数据延迟问题,模型用到的特征在线上拿到的时间点,比训练时拿到的晚得多,这在实时推荐场景特别典型,训练时特征都是事后补齐的,而线上推理时用到的是不完整实时特征,信息量天然打折。
第三类问题的解法,是在训练时就模拟线上可获取的特征集,宁可用"线上能拿到的数据"训练,也不要用"事后才能拿到的完整数据"训练。很多团队把全部精力放在调模型上,却忽略了模拟线上推理环境做训练,结果一上线效果直接对半砍。这个点可以说是线上效果保障里最容易被低估的一环。
7.3 排查知识库速查表
我把这些年踩过的典型问题整理成一张速查表,遇到问题可以按图索骥去排查。
| 症状 | 最可能原因 | 快速验证方法 | 解决方案 |
|---|---|---|---|
| 训练损失不降 | 学习率过大或数据管道出错 | 打印首批输入标签,肉眼核对 | 降低学习率,修数据管道 |
| 验证损失先降后升 | 过拟合 | 看训练与验证损失间距 | 加数据或加正则、早停 |
| 训练集指标极高测试集崩塌 | 数据泄露或评估集过小 | 检查特征是否用了未来信息 | 修正特征处理逻辑,扩评估集 |
| 线上效果明显弱于测试 | 特征不一致或数据延迟 | 跑单测对比特征输出 | 统一特征代码,模拟线上推理 |
| 某类样本全预测错 | 标注噪声或该类样本过少 | 对错误样本聚类分析 | 重新标注,补该类训练数据 |
7.4 一个从“垃圾效果”到“放心交付”的实战复盘
最后一个复盘想认真写下来。去年接了一个文档分类项目,刚开始第一版基线效果很差,准确率只有 71%,业务方根本不愿意用。我当时按老思路调模型,连续调了一个多月,勉强到 79%,卡死了,怎么做都上不去。后来停下来做了个决定:不做任何模型调参,花两周时间去逐条看模型错误的样本,找规律。
这一看发现了真问题。第一,标注文档的标准里有歧义,三个标注员对"求助帖"和"讨论帖"的边界理解不一致,有一大批标签本身就是错的;第二,某些类别的文档极少,模型相当于没学过;第三,文本里大量使用了表格数据,纯文本截断后丢了大半信息。发现这三个问题后,我重新召集业务方统一标注口径,修正了一千多条标签;把对表格类文档的解析能力补上,专门写了解析模块处理表格文本;为稀缺类别从历史库捞数据并做了针对性增强。这次改动之后,准确率直接跳到 88%,而且这次涨上去的指标非常坚挺,不像之前调参调出来的虚高,连续几周都稳定在 87% 以上。
那次复盘让我彻底确认了一件事:AI 工程的瓶颈通常不在模型,而在数据理解和问题定义。会调参是加分项,能把数据问题找出来并摆平才是决定项目生死的关键能力。
8. 扩展方向与个人体会
8.1 以这个项目为底座还能延伸出什么
从零搭完这套 AI 工程链路后,能力是可以复用的,更换模型和数据形态,环节一个都不会变。我第一个做完的项目是文档分类,接下来我把同一套框架迁移到了用户意图识别、内容风险检测和个性化推荐任务上,每个新项目至少省去了 60% 的基建时间。数据工程、评估体系、监控告警、部署流程,这些环节的代码和最佳实践能沉淀成公司的内部工具包,让团队里其他成员起步就站在一个相对可靠的基础上。
目前我个人的重点方向是"数据版本管理"的进一步完善。模型和代码有版本管理是标配,但数据版本的管理在团队里还不够严格,已经发生过两次因为数据集悄无声息变了导致评估结果无法对齐的情况。我准备引入统一的元信息登记,在每次训练时把数据集版本、字段说明、清洗规则都固化成一份信息文件,并纳入团队上线发布流程中检查。
8.2 我在整个过程中最深的三个感受
一是不要急于上复杂方案,先把简易方案跑通,许多高级技巧是在基线不够用时才会发挥价值,过早引入只会增加排查范围。二是学会用数据说话,不要靠感觉调模型,任何调整都先想清楚验证集指标能不能反映这次变化,不能反应就重新设计评估。三是务必要有工程底线,模型效果再好,没有监控告警就别上生产,没有回滚方案就别做版本更新,这是对自己也是对用户负责。
回顾最初"从零开始做 AI 工程"这个决定,我不后悔,这一路踩过的每个坑现在看都是学费,学到了课本里不会写的经验。如果你也正站在这个起点上,建议先把本文提到的最后一个里程碑——负责线上稳定运行的那套机制——当成你交付模型的基本前提去实践,能少走很长一段弯路。