CodeRoadMap
首页路线题库资源库文章社区
CodeRoadMap

程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。

由 程序员柏风 独立维护 · 关于作者

学习

  • 路线图
  • 课程
  • 面试题
  • 文章
  • 我

更多

  • 资源
  • 社区
  • 关于作者
  • 内容说明

© 2026 CodeRoadMap

津ICP备2026012044号-1·津公网安备12011002026155号·coderoadmap@126.com
MLOps 入门/课时/监控与可观测
RawBlame
课时目录12 节

MLOps 入门

  1. 01MLOps 是什么
  2. 02数据工程基础
  3. 03版本控制与 DVC
  4. 04训练与实验跟踪
  5. 05MLflow 与血缘
  6. 06编排与调度
  7. 07CI/CD for ML
  8. 08容器化部署
  9. 09云原生 ML
  10. 10监控与可观测
  11. 11可解释 AI
  12. 12综合练习

监控与可观测

Prometheus/Grafana 与 drift。

30 分钟

监控与可观测

这一课你将能做到

  1. 给 FastAPI 推理服务打 Prometheus 指标:QPS、延迟直方图、预测分布计数
  2. 用 Docker 拉起 Prometheus + Grafana,建一个能看到 p99 延迟的面板
  3. 用 Evidently 对比训练数据与线上近期数据,生成数据漂移报告并读懂 PSI/KS 结论

为什么要学

模型上线后有三个「悄悄变坏」的方式:服务变慢(系统层)、预测分布漂移(数据层)、业务指标下滑(效果层)。第 8 课的探针只能告诉你容器活着,不能告诉你模型判得还准不准——而模型劣化往往在用户抱怨之前已持续数周。

监控就是给模型装仪表盘和预警器。人话:后端监控看「服务死没死」,ML 监控还要看「模型的输入世界变了没有」。本站判题超时模型的典型事故是:站点上线了 Rust 语言支持,提交特征分布突变,模型对所有 Rust 提交给出离谱预测——没有漂移监控,这件事要等运营报障才发现。

先建立图像

三层监控体系:
① 系统层(Prometheus/Grafana):QPS、p99 延迟、错误率、容器资源
   → 回答「服务还能不能用」
② 数据层(Evidently):特征分布 vs 训练基线的漂移
   → 回答「输入世界变了没有」
③ 效果层(业务指标 + 延迟标签回填):线上准确率/F1、超时拦截率
   → 回答「模型判得还准不准」

闭环:③或②报警 → 第 6 课编排器触发重训 → 第 5 课门禁 → 晋升

跟着做

步骤 1:给推理服务打指标

pip install prometheus-client evidently
# src/serve.py(在原服务上叠加指标)
import time
import joblib
import pandas as pd
from fastapi import FastAPI, Request
from prometheus_client import Counter, Histogram, make_asgi_app

app = FastAPI(title="判题超时预测服务")
model = joblib.load("models/timeout-v1.joblib")

PREDICTS = Counter(
    "model_predicts_total", "预测次数",
    ["model", "bucket"])                    # bucket: low/mid/high 概率分段
LATENCY = Histogram(
    "model_predict_latency_seconds", "预测耗时",
    buckets=(0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5))

@app.post("/predict")
def predict(code_lines: int, loop_depth: int,
            lang_java: int, problem_rank: int):
    start = time.perf_counter()
    X = pd.DataFrame([dict(code_lines=code_lines, loop_depth=loop_depth,
                           lang_java=lang_java, problem_rank=problem_rank)])
    proba = float(model.predict_proba(X)[0, 1])
    LATENCY.observe(time.perf_counter() - start)
    bucket = "high" if proba > 0.8 else "mid" if proba > 0.3 else "low"
    PREDICTS.labels(model="timeout-v1", bucket=bucket).inc()
    # 生产环境:此处把 X + proba 异步写入预测日志表,供效果回填与漂移检测
    return {"timeout_probability": round(proba, 4)}

app.mount("/metrics", make_asgi_app())      # 暴露 /metrics 给 Prometheus

步骤 2:Prometheus 抓取 + Grafana 面板

# prometheus.yml
global: { scrape_interval: 15s }
scrape_configs:
  - job_name: timeout-api
    static_configs:
      - targets: ["host.docker.internal:8000"]   # Linux 用宿主机 IP
docker run -d --name prom -p 9090:9090 \
  -v $(pwd)/prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus
docker run -d --name grafana -p 3000:3000 grafana/grafana
# Grafana(localhost:3000, admin/admin) 添加数据源 http://prom:9090 后建面板:
#   p99 延迟: histogram_quantile(0.99, rate(model_predict_latency_seconds_bucket[5m]))
#   QPS:     rate(model_predicts_total[5m])

压测几下接口,回 Grafana 看曲线动起来。PromQL 里 rate(...[5m]) 是「5 分钟窗口增速」,延迟分位必须对 _bucket 直方图算,均值会掩盖长尾。

步骤 3:Evidently 漂移报告

# src/drift_report.py —— 每日对比训练基线与近期数据
import pandas as pd
from evidently.report import Report
from evidently.metric_preset import DataDriftPreset

train_df = pd.read_parquet("data/processed/judge_clean.parquet")   # 基线
today_df = train_df.sample(1000, random_state=7)                   # 演示:近期数据

report = Report(metrics=[DataDriftPreset()])
report.run(reference_data=train_df, current_data=today_df)
report.save_html("drift.html")
report.save_json("drift.json")

result = report.as_dict()
drifted = [c["column"] for c in result["metrics"][1]["result"]["drift_by_columns"].values()
           if c["drift_detected"]]
print("漂移特征:", drifted or "无")
# 集成方式:编排器每日跑本脚本,drifted 非空则告警/触发重训
python src/drift_report.py
# 打开 drift.html:每个特征一张分布对比图,附 PSI/KS 统计量与是否漂移的结论

讲清楚要点

  1. 监控要分层设 SLO:系统层定义可用性与 p99 延迟(如「99% 请求 < 100ms」),数据层定义漂移阈值,效果层定义业务底线(如「超时拦截率 < 70% 告警」)。没有 SLO 的监控只是录像回放。
  2. 数据漂移 ≠ 概念漂移:数据漂移是 P(X) 变了(新增语言、题目类型变化),概念漂移是 P(y|X) 变了(判题机升级、超时规则调整)。前者看特征分布(Evidently),后者必须看真实标签回填后的效果。
  3. 预测留痕是效果监控的前提:每次请求把「特征 + 预测 + 模型版本」写入日志表,真实结果出来后回填标签。没有留痕,线上准确率永远算不出来。
  4. 标签延迟要设计:超时结果几秒内可得,可以实时回填;「用户是否流失」要等 30 天,只能用代理指标(点击率)+ 延迟评估。设计管道时先画清楚每个特征/标签的时间轴。
  5. 告警必须连 runbook:每条告警写明「现象 → 排查三步 → 处置动作 → 升级路径」。报警器没人会处理,等于半夜装了个只会响不会救火的烟感。

你可能会懵的地方

  • 没有真实标签时怎么知道模型还准不准? 三招:代理指标(业务转化、人工抽检准确率);延迟标签回填(结果出来再算一次历史准确率);输入漂移作先行指标(漂移不一定掉点,但掉点几乎都伴随漂移或概念变化)。
  • 检测到漂移就该立刻重训吗? 不。先分级:轻微漂移(PSI < 0.1)观察即可;持续中度漂移触发 challenger 重训对比;效果确实下降才晋升。盲目重训会引入「没坏先修」的新风险,且掩盖概念漂移的真因。
  • PSI 和 KS 怎么选? PSI(群体稳定性指数)输出单一数值、对分箱敏感,适合日度看板(<0.1 稳定 / 0.1~0.25 关注 / >0.25 显著漂移);KS 是分布距离的非参检验,小样本更稳。两者都给「变化了吗」,给不了「变化好不好」——好坏要连到效果层。
  • Prometheus 标签能不能放 user_id? 不能。标签基数爆炸(每用户一个时间序列)会打爆时序数据库。模型版本、概率分段这类低基数值可以,user_id 只进日志/明细表,不进指标。
  • 什么时候用 Pushgateway? 批量任务(第 9 课的 batch_score)进程短命、抓取可能错过,把指标主动 push 给网关再被 Prometheus 拉取。常驻服务一律用标准 /metrics 抓取,不要滥用网关。

错法对照

错法问题正解
只监控 CPU/内存/错误率模型劣化完全不可见三层齐备:系统 + 数据漂移 + 效果
延迟监控只看平均值长尾卡顿被平均掉p95/p99 分位 + 直方图
每条请求全量写详细日志存储成本与 PII 风险双高采样落盘 + 敏感字段脱敏
指标标签带 user_id时间序列基数爆炸低基数标签(版本/分段),明细进日志
报警发了没人知道怎么处理疲劳后告警被静音每条告警绑 runbook,定期演练

卡点急救

  1. Grafana 面板无数据:先确认 Prometheus Targets 页目标是 UP;数据源地址要写容器网络可达地址,不是 localhost。
  2. histogram_quantile 结果恒为 0:算分位必须用 _bucket 后缀的直方图指标,且查询窗口内要有新增样本(先压测产生流量)。
  3. Evidently 报列类型不匹配:基线与当前数据的列类型/枚举必须一致,先过第 3 课的 schema 校验再进漂移检测。

面试常问

  • 设计一个线上模型的监控体系。 三层:系统层 Prometheus/Grafana(QPS、p99、错误率,定 SLO);数据层 Evidently 日度对比训练基线(PSI/KS 分特征报警);效果层预测留痕 + 标签回填计算线上 F1 与业务指标。漂移与效果双门禁接入重训闭环,所有告警配 runbook。
  • 数据漂移和概念漂移的区别与检测方法? 数据漂移是输入分布 P(X) 变化,用 PSI/KS 对比特征分布即可发现;概念漂移是输入到输出的映射 P(y|X) 变化,必须依赖真实标签回填后的效果对比(或按新标签重训对比历史样本的预测差异)。工程上前者是先行指标,后者是最终裁决。
  • 为什么延迟监控要看 p99 而不是平均值? 用户体感由最慢请求决定;平均会把长尾摊平——99% 的 10ms 和 1% 的 5s 平均后只有 60ms,看似健康实则每百次请求就有一个超时。分位数 + 直方图才能定位长尾来源。

自测三问

  1. 三层监控各自回答什么问题?分别用什么工具?
  2. 预测留痕表需要哪些字段?为什么它是效果监控的前提?
  3. PSI 0.3 意味着什么?接下来该做什么、不该立刻做什么?

小结一句话

模型监控 = 系统层保可用(Prometheus p99/SLO)+ 数据层报漂移(Evidently PSI/KS)+ 效果层裁决策(预测留痕与标签回填),三层接进重训闭环才算完整。

延伸

  • Prometheus Python 客户端——四种指标类型与 ASGI 集成的官方说明。
  • Evidently 官方文档——漂移预设、自定义指标与 CI 集成。
  • 下一课:可解释 AI——用 SHAP/LIME 回答「模型为什么这么判」,支撑合规与业务沟通。
加载本节练习…
← 上一课云原生 ML下一课 →可解释 AI