模型没有报错,为什么效果在变差:特征监控到底要看什么

模型系统最危险的故障,经常不是接口 500,也不是服务超时,而是模型正常返回,但决策质量正在变差

推荐还能返回商品,风控还能给出分数,广告还能完成排序,搜索还能出结果。监控看起来一切正常:QPS 正常、错误率正常、P99 正常、模型服务也没有重启。但业务指标开始下滑,点击率变差,误杀率变高,转化率下降,投诉增加。

这类问题的根因,很多时候不是模型代码坏了,而是模型输入的特征变了。特征缺失、默认值变多、实时特征延迟、上游口径变更、枚举值新增、分布漂移、线上离线不一致,都会让模型在一个它没有见过的输入空间里做判断。

一、模型系统最怕静默故障

传统后端服务的故障通常比较显性:

  • 接口 500;
  • 数据库超时;
  • 缓存击穿;
  • 消息堆积;
  • 线程池打满。

这些故障会直接体现在错误率、延迟、资源利用率、队列长度上。但模型系统有一种特殊故障:系统还在正常运行,只是输出质量变差

接口层:200 OK
模型层:正常返回 score
特征层:部分特征全是默认值
业务层:转化率下降、误杀率上升、用户体验变差

如果只看服务监控,你会觉得系统没问题;如果只等业务指标报警,通常已经晚了。特征监控的价值,就是在模型效果明显变坏之前,提前发现输入正在偏离预期。

二、特征监控和服务监控有什么不同

服务监控回答的是:系统有没有稳定地提供服务。特征监控回答的是:模型吃进去的数据还可信吗。

监控类型关注对象典型指标发现的问题
服务监控接口和系统运行状态QPS、错误率、P95/P99、CPU、内存服务不可用、依赖超时、容量不足
数据监控数据产出和链路质量产出延迟、行数、分区缺失、重复率ETL 失败、上游断流、数据重复
特征监控模型输入的稳定性缺失率、默认值比例、分布漂移、新鲜度、线上离线差异特征变坏、口径变化、训练服务偏差
模型监控模型输出和业务效果预测分布、AUC、CTR、转化率、误杀率模型衰退、策略失效、概念漂移

这几类监控不是替代关系,而是递进关系。服务监控告诉你系统是否活着;特征监控告诉你模型是否还在吃正常的数据;模型监控告诉你输出是否还有效;业务监控告诉你最终结果是否还健康。

三、第一层:特征可用性

特征监控最基础的一层,是判断特征有没有按预期出现。

指标含义常见问题
缺失率特征为空、null、无法取到的比例上游任务失败、Join key 不匹配、覆盖率下降
默认值比例特征被填成默认值的比例在线取数失败、fallback 过多、特征服务降级
零值比例数值特征为 0 的比例计数任务异常、窗口没有数据、业务断流
覆盖率有有效特征值的请求或样本比例新用户、新商品、新城市覆盖不足
枚举合法率类别特征是否落在已知枚举集合内上游新增枚举、编码表变更、脏数据进入

一个常见坑是只监控 null,不监控默认值。线上系统为了可用性,往往会把缺失特征填成 0、-1、unknown、平均值或历史值。接口不会失败,但模型看到的是另一种分布。

user_order_cnt_7d 缺失率:0%
user_order_cnt_7d 默认值比例:45%

结论:不是没有缺失,而是缺失被默认值掩盖了

所以特征平台要明确记录缺失和默认值语义。0、unknown、缺失、未覆盖、超时降级,不能全部混成一个值。

四、第二层:特征新鲜度

很多特征不是有没有的问题,而是新不新。

比如风控模型里的「用户近 5 分钟失败支付次数」、推荐模型里的「商品近 10 分钟曝光次数」、履约模型里的「商家当前压单量」。这些特征如果延迟 30 分钟,值仍然存在,但已经失去意义。

指标含义例子
feature_lag当前时间减去特征最新更新时间实时特征已经 20 分钟未更新
window_delay窗口结束到结果可见之间的延迟10:00 窗口 10:08 才写入 Online Store
source_lag上游事件流的消费延迟Kafka lag 持续增长
materialization_lag离线到在线物化延迟批任务产出后 1 小时才进入 Redis

新鲜度监控要按特征类型设置阈值。用户长期画像延迟一天可能没问题;实时风控特征延迟 5 分钟就可能不可接受。统一用一个延迟阈值,会导致该报警的不报警,不该报警的一直报警。

五、第三层:特征分布漂移

特征存在,也足够新,不代表它还正常。它的分布可能已经变了。

比如:

  • item_price 的中位数突然翻倍;
  • user_age 缺失率不变,但 18 岁以下占比突然上升;
  • shop_order_cnt_1h 的 P99 降到接近 0;
  • city_id 新增了一批模型训练时没见过的城市;
  • device_type 的 top1 从 iOS 变成 unknown。

数值特征通常看这些统计量:

  • 均值、标准差、最小值、最大值;
  • P50、P90、P95、P99;
  • 分桶占比;
  • 异常值比例;
  • 和训练基线或历史窗口的距离。

类别特征通常看这些统计量:

  • top N 枚举值占比;
  • unknown / other 比例;
  • 新枚举数量;
  • 低频枚举数量;
  • 训练集中未出现过的类别比例。

分布漂移监控的核心不是追求一个神奇指标,而是回答:线上输入和模型训练时相比,是否已经变成了另一个世界

六、PSI、KS 这些指标怎么用

实际做漂移监控时,经常会用 PSI、KS、KL 散度、JS 散度、Wasserstein Distance 等指标。它们都在衡量两个分布是否相似,但适用场景不完全一样。

指标适合场景注意点
PSI业务上常用于特征稳定性、分桶后分布对比依赖分桶方式,小样本时不稳定
KS数值特征两组分布的累积分布差异更适合连续数值,不能解释业务原因
KL 散度概率分布差异对 0 概率敏感,通常需要平滑
JS 散度更稳定的分布差异度量仍然需要结合业务阈值解释
分位数差异延迟、价格、计数类特征简单直观,适合告警解释

PSI 的思路很直观:把训练期或基线期的特征分布分成多个桶,再比较当前线上流量在这些桶里的占比是否变化很大。

PSI = Σ (actual_pct - expected_pct) * ln(actual_pct / expected_pct)

但不要把 PSI 阈值当成通用真理。不同业务、不同特征、不同流量规模,对漂移的容忍度不同。一个强特征轻微漂移可能就影响很大;一个弱特征大幅漂移可能没有业务影响。

更稳妥的做法是:漂移指标只负责告诉你「这里不一样了」,是否需要报警还要结合流量占比、特征重要性、模型输出变化和业务指标。

七、先区分几种漂移

不是所有漂移都代表故障。特征监控要能区分至少四类情况。

类型含义例子处理方式
数据漂移输入特征分布变了新城市上线导致 city_id 分布变化评估模型是否覆盖新流量
概念漂移特征和标签之间的关系变了促销期间价格敏感度变化重训模型或调整策略
标签漂移目标变量分布变了整体转化率下降排查业务环境和样本构造
管道故障数据链路或口径异常某个实时特征全变成 0回滚、修复上游、降级

数据漂移不一定是坏事。新品类上线、新区域扩展、节假日活动都会带来自然漂移。真正需要快速处理的是管道故障和不可解释的漂移。

八、基线怎么选

漂移监控一定要回答「和谁比」。常见基线有三种。

基线适合场景风险
训练集基线判断线上输入是否偏离模型训练分布训练集太老时会让正常业务增长都变成漂移
滚动历史基线判断当前窗口是否偏离最近稳定状态慢性漂移可能被滚动基线吞掉
分群基线新老用户、城市、渠道、设备分别比较维度过多会造成告警爆炸

生产里通常要组合使用:

  • 和训练集比,判断模型是否仍然在熟悉的分布上工作;
  • 和昨天、上周同周期比,发现突发异常;
  • 按核心分群比,避免整体正常掩盖局部问题。

比如整体缺失率只有 2%,看起来没问题;但新用户缺失率是 35%,某个城市缺失率是 60%,这才是真正影响模型的地方。

九、线上离线一致性也要监控

特征监控不只看线上分布,还要看同一个请求在离线和线上是否算出同样的特征。

常见做法是从线上流量里抽样,记录请求上下文、模型版本、特征版本、线上特征值和特征来源。离线系统再按同一批请求回放一次特征计算,对比两边结果。

online_feature_log
request_id
model_version
feature_view
feature_version
entity_key
online_value
feature_time
visible_time
source

离线回放后对比:
online_value vs offline_recomputed_value

如果同一个特征长期出现线上离线差异,就说明两套计算逻辑、数据源、窗口定义或默认值策略在分叉。这类问题往往比单纯分布漂移更危险,因为它直接破坏训练和推理的一致性。

十、特征告警怎么设计

特征监控如果直接把所有异常都报警,会很快变成噪音。一个模型可能有几百到几千个特征,每个特征都有缺失率、新鲜度、分布、枚举、延迟等指标,简单阈值会把人淹没。

告警设计要考虑几件事:

  • 连续窗口:不要单个窗口异常就报警,要求连续 N 个窗口异常。
  • 流量占比:影响 0.1% 流量和影响 40% 流量不是一个级别。
  • 特征重要性:核心特征漂移优先级更高,低价值特征可以只记录。
  • 模型输出联动:特征异常是否同时导致 score 分布变化。
  • 业务护栏:是否伴随 CTR、转化率、误杀率等指标变化。
  • 分群影响:整体不明显但关键人群异常,也应该提升优先级。

一个更可用的告警规则,不是「PSI > 0.2 就报警」,而是:

核心特征 PSI 连续 3 个窗口超过阈值
且影响流量超过 10%
且模型 score 均值或分位数出现同步变化
则触发 P1 告警

普通特征单窗口漂移
只进入日报或看板,不打扰值班人

特征告警的目标不是证明某个统计量异常,而是帮助人判断:这件事值不值得立刻处理。

十一、不同场景重点看什么

不同业务模型最该看的特征监控不一样。

场景重点特征重点监控
推荐用户行为、商品热度、类目偏好、曝光点击统计新鲜度、冷启动覆盖率、热门 item 分布、score 分布
广告广告主、预算、出价、点击转化统计预算状态延迟、CTR/CVR 特征漂移、分渠道分布
风控设备、账户、交易频次、失败次数、黑名单命中实时特征延迟、缺失率、异常枚举、误杀率联动
搜索排序Query、文档质量、相关性、点击反馈Query 分布漂移、新词覆盖、文档特征缺失
履约调度位置、距离、商家压单、骑手状态、天气实时性、地理特征缺失、城市分群异常

比如风控更怕实时特征延迟和缺失,因为一个关键风险特征没拿到,可能直接放过高风险交易。推荐更怕行为分布漂移和新商品覆盖不足,因为模型会在冷启动流量上变得保守或失真。

十二、Feature Store 应该承担什么角色

Feature Store 不只是存特征,也应该成为特征监控的天然落点。因为它最清楚:

  • 特征定义是什么;
  • 特征属于哪个实体;
  • 特征从哪个数据源来;
  • 特征多久更新一次;
  • 哪些模型正在使用这个特征;
  • 线上服务取到的值是什么;
  • 离线训练时用的是哪个版本。

因此,一个成熟 Feature Store 应该提供:

能力说明
特征画像展示每个特征的分布、缺失率、新鲜度、枚举值
基线管理记录训练集基线、历史稳定基线、分群基线
线上采样采集线上请求中的特征值和模型版本
离线回放对线上样本重新计算离线特征,检查一致性
影响分析知道一个异常特征影响哪些模型和业务
告警治理按 owner、重要性、流量影响和连续窗口生成告警

这也是为什么特征监控不应该只是 Grafana 上几条孤立曲线,而应该和 Feature Registry、模型版本、实验平台、线上日志打通。

十三、一次特征异常该怎么排查

当收到一个特征漂移或缺失告警时,可以按这个顺序排查。

1. 先确认影响范围
   哪个模型、哪个特征、哪个分群、多少流量?

2. 看特征可用性
   缺失率、默认值比例、覆盖率是否异常?

3. 看新鲜度
   特征是否延迟?上游数据源是否断流?Online Store 是否写入失败?

4. 看分布变化
   均值、分位数、topN、PSI/KS 是否变化?变化从什么时候开始?

5. 看上游变更
   数据源、ETL、Flink 任务、特征定义、枚举表是否发布过?

6. 看模型输出
   score 分布、分桶通过率、排序位置是否同步变化?

7. 看业务指标
   CTR、CVR、误杀率、投诉率、履约指标是否受影响?

8. 决策
   回滚特征、切默认值、降级模型、重训模型,还是只记录观察?

这个排查路径的重点是从输入到输出再到业务结果,而不是一上来就重训模型。很多线上效果问题,重训只能掩盖问题,不能修复上游特征链路。

十四、几个常见误解

误解一:模型服务没报错就没问题

模型服务没报错,只能说明系统还能返回结果,不能说明结果仍然可靠。特征缺失、分布漂移和口径变更都可能在 200 OK 里发生。

误解二:只看模型输出就够了

模型输出是结果,特征是原因。只看 score 分布,通常已经晚了一步;提前发现输入异常,才能更快定位问题。

误解三:漂移一定是坏事

漂移可能是自然业务变化,比如节假日、新城市、新品类、新渠道。真正的问题是不可解释的漂移、重要特征漂移、伴随模型输出和业务指标变化的漂移。

误解四:所有特征都要同等监控

不是。几千个特征如果同等告警,值班人会被噪音淹没。应该按特征重要性、使用模型数量、影响流量、业务风险做分级。

结语

模型上线以后,真正难的是持续确认:模型今天吃进去的数据,还是不是训练时那种数据。

特征监控要看的不是一条曲线,而是一套链路:特征是否存在,是否新鲜,分布是否稳定,线上离线是否一致,模型输出是否随之变化,业务指标是否受到影响。

如果说 Feature Store 管理的是模型输入资产,那么特征监控就是这些资产的健康检查。它不保证模型一定有效,但它能让模型变差这件事更早被看见、更快被定位、更少靠运气。

一句话总结:模型没有报错,不代表模型系统没坏;特征没有被监控,模型效果就只能靠业务指标事后发现

延伸阅读