机器学习模型在训练集上表现优异,并不意味着部署后就能一直稳定生效。生产环境的数据分布、业务规则和用户习惯都在不断变化,模型原本学到的规律会逐渐失效,这种现象被称为模型退化。持续评估(Continual Evaluation)正是针对这一问题提出的系统性做法,它要求我们在模型服务期间,持续收集真实输入输出与业务反馈,周期性地测算模型效果指标,从而在准确率明显下跌之前发现异常。

模型退化的主要成因与表现
要监控模型退化,首先得弄清楚模型为什么会退化。最常见的原因是数据分布漂移(Data Drift),也就是生产数据的特征分布和训练时明显不同。例如信贷模型训练时收入字段集中在每月五千到两万,上线半年后大量新用户收入超过五万,模型对该区间的预测逻辑就不够可靠。另一种情况是标签漂移(Label Drift),比如用户转化意愿随季节波动,正样本比例从百分之五涨到百分之十五,阈值不变的模型会大量误判。
除了数据本身,工程侧的变动也会引发退化。特征管道如果被修改,比如某个字段的缺失值填充方式从均值改成中位数,而模型训练时使用的是旧逻辑,那么线上传入的特征含义就发生偏移。还有模型依赖的第三方接口返回结构变化,也会导致输入异常。退化在业务上的表现通常是核心指标缓慢下降:推荐系统的点击率每周掉零点几个百分点,风控系统的捕获率在不觉间下滑,等到人工复盘时往往已经持续了数周。
因此,持续评估并不是等月报出来再看auc,而是把监控粒度细化到天甚至小时级别。我们需要建立基线(baseline),明确模型健康时的指标区间,再对实时指标做偏离度分析。只有理解退化来自哪一层,才能选对监控手段,而不是盲目告警造成运维疲劳。
基于统计检验与指标追踪的监控方案
实践中最落地的持续评估方案是结合统计漂移检测和业务指标预警。对于数值或类别特征,可以计算群体稳定性指数PSI(Population Stability Index)。当PSI小于零点一说明分布基本稳定,零点一到零点二需关注,大于零点二则分布显著变化。下面是一段用Python计算两个数据集某特征PSI的示例代码,实际中可每天跑一次,把结果写入监控表。
import numpy as np
def calc_psi(expected, actual, bins=10):
# expected为训练集特征分箱占比,actual为线上当日特征
cut_points = np.percentile(expected, np.linspace(0, 100, bins + 1))
cut_points[0] = -np.inf
cut_points[-1] = np.inf
def bucket_ratio(data):
return np.histogram(data, bins=cut_points)[0] / len(data)
e_ratio = bucket_ratio(expected)
a_ratio = bucket_ratio(actual)
psi = np.sum((a_ratio - e_ratio) * np.log((a_ratio + 1e-6) / (e_ratio + 1e-6)))
return psi
train_income = np.random.normal(10000, 3000, 10000)
online_income = np.random.normal(11000, 3500, 2000)
print(calc_psi(train_income, online_income))
除了特征层,模型输出层的退化更直接地反映在auc、f1、业务转化率上。我们可以维护一个带时间戳的指标流水表,当连续三天的auc低于基线两个标准差时触发告警。相比单点判断,这种滑动窗口方式能过滤偶发波动。许多团队还会引入影子模型(Shadow Model),即新训练的候选模型与老模型同步接收流量但不生效,通过对比两者在真实输入上的输出差异,判断老模型是否已被环境甩开。
需要强调的是,监控不能只盯机器学习指标。模型退化常常先表现为上游数据延迟、特征缺失率上升,这些运维指标应并入同一看板。一个合理的持续评估体系,应该让数据科学家看到特征漂移,让业务方看到转化变化,让运维看到管道健康度,三者交叉验证才能定位退化根源。
用定时任务搭建轻量持续评估流水线
中小团队不一定需要昂贵的MLOps平台,用定时任务和脚本就能搭起基础持续评估流水线。核心思路是:每天凌晨拉取前一日生产预测日志与真实标签(或延迟反馈),计算PSI、auc等指标,若超阈值则发消息到运维群。下面示例展示如何用伪代码组织这个流程,其中标签可能来自隔日回流的数据库。
import json
from datetime import datetime, timedelta
def fetch_logs(date_str):
# 从日志系统读取某天预测记录,返回特征与预测值
return []
def fetch_labels(date_str):
# 从业务库读取同日真实标签
return []
def evaluate():
yesterday = (datetime.now() - timedelta(days=1)).strftime('%Y-%m-%d')
logs = fetch_logs(yesterday)
labels = fetch_labels(yesterday)
features = [x['feat'] for x in logs]
preds = [x['pred'] for x in logs]
y_true = [l['label'] for l in labels]
psi = calc_psi(train_features, features)
auc = compute_auc(y_true, preds)
if psi > 0.2 or auc < baseline_auc - 0.02:
send_alert(f'模型退化预警 date={yesterday} psi={psi} auc={auc}')
if __name__ == '__main__':
evaluate()
这个流水线的优势是透明、可控,所有逻辑都在自己代码里。但它要求标签能及时回流,对于标签天然延迟的场景(如贷款是否违约要半年后才知道),就要用代理指标,比如用申请通过率结合短期逾期率来近似监控。持续评估不是追求绝对精确,而是尽早发现趋势性恶化。
当告警频繁时,团队应建立响应手册:特征漂移先查管道代码,标签漂移先查业务动作,模型指标掉但特征正常则考虑重训。把持续评估嵌入到模型的整个生命周期,才能把退化的代价压到最低,而不是等模型烂在生产环境里才被动替换。
continual_evaluationmodel_degradationmodel_monitoring修改时间:2026-08-16 21:10:35