很多团队都经历过同一个魔幻时刻:
你在 notebook 里把模型调到 0.9+,验证集漂亮得像 PPT 封面;一上生产,效果直接塌成 0.6,甚至更差。然后会议室里开始出现熟悉台词:
- “是不是模型太弱?”
- “要不要换更大的底座?”
- “再调调参数吧。”
坦白说,这类讨论大多在浪费时间。我的判断很直接:多数线上劣化,不是模型问题,而是训练—服务偏差(train/serve skew)问题。
你训练时喂给模型的世界,和线上推理时让它面对的世界,根本不是一个世界。模型不是不聪明,是你在训练时教它开自动挡,上线时却把车换成手动挡,还怪它不会踩离合。
一、什么叫训练—服务偏差?
一句话:同一个特征名,背后不是同一个计算过程。
看起来你在训练和线上都用了 user_7d_ctr、is_new_user、session_depth,但细看实现:
- 训练侧用 pandas,线上用 Spark/Flink
- 训练侧缺失值填 0,线上填全局均值
- 训练侧按 UTC 切日,线上按本地时区切日
- 训练侧先 winsorize 后 log,线上顺序反了
- 训练样本用了“事后才知道”的字段,线上永远拿不到
这些差异单看都“不大”,叠加起来就是灾难。你以为是同一个特征,模型看到的却是两套语义。
这不是精度波动,这是输入分布被你自己改写了。
二、为什么这个坑反复出现?
因为很多团队把特征工程当“研究代码”,把线上推理当“工程代码”,中间靠口头对齐。口头对齐在 demo 阶段能活,在生产阶段必死。
1) 组织结构把“同一件事”拆成两拨人
算法同学写训练 pipeline,平台同学写 serving pipeline。两边都很专业,但目标函数不同:
- 算法追离线指标
- 平台追吞吐和延迟
最后出现经典局面:离线指标很好,线上 SLA 也没超,但业务指标掉了。因为没人对“特征语义一致性”负总责。
2) 代码复用是假象,逻辑复用才是关键
很多人说“我们复用了函数库”。问题是你只复用了工具函数,没复用完整变换图:字段依赖、执行顺序、时间窗口、缺失策略、版本边界。这些才是语义。
3) 评审机制在看“能不能跑”,不看“是不是同一个东西”
上线评审常问:
- 延迟多少?
- QPS 顶不顶得住?
- 回滚脚本有吗?
却很少问:
- 训练样本的特征分布和线上实时分布,PSI/KL 差距多少?
- 黄金样本在训练和服务两条链路产出的特征是否逐列一致?
- 时间切分是否保证了“当时可得性”?
你不问,就默认它一致;默认一致通常就是不一致。
三、别再迷信“更大模型能覆盖脏输入”
很多团队在 skew 出现后第一反应是升级模型:从小模型换大模型,从单塔换多塔,甚至直接上多模态。结果通常是:短期有点提升,长期继续崩。
原因很简单:
- 大模型可以提高容错,但不能修复系统性输入污染
- 输入语义漂移是“数据契约破坏”,不是“参数容量不足”
- 你今天靠容量硬扛,明天数据再漂一点,照样出事
用一句不好听但真实的话:用更大模型去掩盖 skew,就像用更厚的粉底遮结构性骨折。
四、真正有效的解法:把“特征”当产品,不当脚本
我建议把特征系统升级为三层治理,而不是继续堆 patch。
第一层:单一计算真相(Single Source of Feature Truth)
核心原则:特征只计算一次,多处消费,不允许二次实现。
- 训练、回放、在线推理都调用同一份特征定义
- 特征定义必须版本化(含依赖、窗口、缺失规则)
- 任何改动都生成新版本,不允许 silent overwrite
这一步做不到,后面全是补丁美学。
第二层:上线前“黄金样本对拍”
准备一组覆盖边界条件的黄金样本(新用户、老用户、异常值、跨时区、缺字段等),在训练链路和服务链路分别计算特征,逐列比对。
验收标准别写“差不多”,要写:
- 数值列容差阈值(如 abs diff < 1e-6)
- 枚举列完全一致
- 缺失模式一致
- 派生列依赖路径一致
对拍不过,禁止上线。 这条规则会得罪人,但会救命。
第三层:上线后分布守卫(Distribution Guardrail)
模型上线不是结束,而是开始。你需要持续监控:
- 特征分布漂移(PSI、JS/KL)
- 特征可用率(null ratio、超时率)
- 关键业务切片(新客/老客、地区、设备)上的输出稳定性
并且预先定义自动化动作:
- 漂移越过阈值 → 自动降级到上一稳定版本
- 缺失率异常 → 切换兜底策略并告警
- 关键切片崩塌 → 触发人工值班流程
没有“可执行的回滚”,所有监控都只是赛博烟花。
五、从工程问题到治理问题:你到底在奖励什么行为?
很多组织明知有 skew,仍长期不修,不是技术不会,是激励错了。
如果你的绩效体系奖励的是:
- 模型迭代速度
- 新功能上线数量
- 单点离线指标
那团队自然会把“特征一致性”当阻碍,因为它短期拖慢节奏。
你要改的是激励函数:
- 把线上一致性通过率纳入发布门槛
- 把回滚时长(MTTR)纳入核心指标
- 把“避免事故”计入可见贡献,而不是只奖励“造新东西”
系统会长成你奖励的样子。 这是工程世界最朴素、也最残酷的规律。
六、给正在做 AI 产品的团队一个硬结论
如果你现在还在:
- 训练一套代码、线上一套代码
- 特征定义散落在脚本和 SQL 里
- 上线不做黄金样本对拍
- 漂移监控只有 dashboard,没有自动动作
那你不是“偶尔会出线上事故”,你是已经在事故轨道上,只是等时间戳。
真正成熟的 AI 团队,不是离线分数最高的团队,而是能长期维持“训练语义 = 服务语义”的团队。前者靠天赋,后者靠制度。天赋会波动,制度才可复制。
所以,别再问“模型怎么又不稳定”。先问一句更扎心但更有用的话:
我们有没有把特征工程,从个人技巧升级成组织能力?
如果没有,现在就改。越晚改,补的窟窿越贵。
—— https://www.80aj.com