返回 AI 测试成长路线
Phase 01 / AI Quality Foundation 02

测试工程师需要的机器学习与统计基础教程

不从公式背诵开始,而是围绕智能客服工单分类与回答评估,学会用样本、指标、置信区间和一致性证据回答同一个问题:这个模型到底能不能上线。

12 个章节混淆矩阵 + PRF统计证据与上线决策
01

先把「懂概念」升级成「能科学评估」

智能客服贯穿案例

案例:智能客服工单分类与回答评估

系统做两件事:把工单自动分类到退款、物流、账号或咨询,并生成回复客户的回答。你负责回答「新版模型能不能上线」——业务方甩给你一句话:准确率 95%,应该没问题吧?

版本评估决策链

原始工单文本与字段
分类模型退款/物流/账号/咨询
回答模型生成回复
人工复核抽样与仲裁
上线决策灰度或回退
准确率 95% 本身不能回答任何问题。这篇教程的任务,是让你能说出「用什么样本、按什么指标、在多大置信下、由谁复核」,并最终产出一份可决策的版本对比报告。

学完后的六份产出

产出对应章节
分层评估样本(含分布说明)样本量与抽样
一张混淆矩阵混淆矩阵
一套 Precision / Recall / F1 指标PRF 选择
一份人工标注一致性报告标注者一致性
一份模型 A/B 版本对比报告A/B 与显著性
一个上线、灰度或回退结论版本对比与上线
02

先分清问题类型,再选评估指标

分类 / 回归 / 聚类

三类问题的区别

类型输出智能客服例子评估指标
分类离散类别工单分到退款/物流/账号/咨询混淆矩阵、Precision、Recall、F1
回归连续数值预测退款金额、回答延迟、等待时长MAE、RMSE、P95
聚类无标签分组把相似问题聚成主题,发现新客诉模式轮廓系数、ARI、纯度

对测试工程师的意义

  • 指标不能跨问题类型混用:给分类模型看 RMSE,给回归模型看 F1,都是错位的。
  • 分类是最常见也最好解释的,这篇教程以它为主;回归至少要知道用 MAE/RMSE 而不是准确率。
  • 聚类用于探索,不直接回答「对不对」,而是回答「分组是否稳定、是否可解释」。
拿到一个 AI 需求,第一步是问「它是分类、回归还是聚类」。这个问题决定了后面所有指标和断言怎么写。
03

用混淆矩阵同时看错判和漏判

把准确率拆开

二分类混淆矩阵(以「退款工单」为正类)

分类器每一条预测都会落入四个格子:真正例 TP、假正例 FP(误报)、假负例 FN(漏报)、真负例 TN。只看准确率,这四个格子的差异会被总数抹平。

100 条工单的预测结果

预测:退款预测:非退款
实际:退款TP = 30FN = 5(漏报:该退的没退)
实际:非退款FP = 3(误报:不该退的退了)TN = 62

怎么读这张表

  • 漏报(FN=5):真实退款工单被分到其他类,客户反复追问,体验最差。
  • 误报(FP=3):非退款工单被当成退款,可能触发错误处理流程。
  • 准确率 = (30+62)/100 = 92%,看不出这两类错误的代价差异。

多分类怎么办

工单有四个类别时,逐类做 one-vs-rest:把「退款」当正类、其余三类当负类,得到退款类的混淆矩阵;其他类别同理。每一类单独看,而不是只看总准确率。

04

Precision、Recall、F1 按业务代价选择

不是越高越好

两个指标的定义

Precision = TP / (TP + FP):预测为退款的人里,有多少真退。Recall = TP / (TP + FN):真实退款里,有多少被找出来。F1 是两者的调和平均,用于给一个综合分。

智能客服里的取舍

场景优先指标为什么
自动退款Precision误报直接造成资金损失,宁可漏给人工
高危工单识别Recall漏报导致事故升级,宁可多召回让人工筛
通用报告F1没有明确倾向时给一个平衡数
路由到人工Recall错误路由可接受,漏路由不可接受
用 sklearn 算三件套
from sklearn.metrics import confusion_matrix, precision_score, recall_score, f1_score

y_true = [1, 1, 0, 1, 0, 0, 1, 1, 0, 0]   # 1=退款工单
y_pred = [1, 0, 0, 1, 0, 1, 1, 1, 0, 0]

tn, fp, fn, tp = confusion_matrix(y_true, y_pred).ravel()
print("TP", tp, "FP", fp, "FN", fn, "TN", tn)
print("Precision", round(precision_score(y_true, y_pred), 3))
print("Recall", round(recall_score(y_true, y_pred), 3))
print("F1", round(f1_score(y_true, y_pred), 3))
报告必须写清「按哪个类别、以什么为正类、阈值是多少」。同样的模型,阈值一改,Precision 和 Recall 会此消彼长,F1 也会跟着变。
05

准确率 95% 也可能毫无意义

类别不平衡与阈值

为什么 95% 是陷阱

如果 99% 的工单都是「咨询」,模型把一切都判成「咨询」,准确率就是 99%。它什么都没学会,但数字很好看。类别越不平衡,准确率越会骗人。

应对类别不平衡

手段做法注意
换指标用每类 Precision/Recall/F1 和混淆矩阵不要只看总体准确率
按类别加权F1 macro / weighted 反映小类别macro 平均每类权重,weighted 按样本数
调阈值对少数类降低判定阈值提高 Recall阈值改变要重新评估误报成本
补样本扩充少数类样本,必要时做类内分层不能凭空造数据掩盖分布
观察阈值影响
from sklearn.metrics import precision_recall_curve

# 模型输出每个样本属于"退款"的概率,而不是直接给类别
proba = model.predict_proba(X)[:, 1]
precision, recall, thresholds = precision_recall_curve(y_true, proba)

# 找 Recall >= 0.95 的最高 Precision 阈值
for p, r, t in zip(precision, recall, thresholds):
    if r >= 0.95:
        print("阈值", round(t, 3), "Precision", round(p, 3), "Recall", round(r, 3))
报告指标时必须同时报告类别分布。没有分布背景的准确率,不具备任何决策价值。
06

均值、P95、方差和置信区间分开看

平均数会骗人

回答延迟的三种读法

均值回答延迟 1.2 秒听起来不错;但如果 5% 的请求要 8 秒,长尾客户体验已经崩了。均值被少数慢请求拉高或掩盖,P95 专门盯长尾,方差描述波动大小。

四个统计量各回答什么问题

统计量回答在客服评估里的用法
均值整体水平平均回答延迟、平均评分
P95 / P99长尾与最差体验5% 最慢请求多慢、99% 请求是否达标
方差/标准差波动是否稳定同一输入多次生成的评分漂移
置信区间样本估计的可信范围评估集 200 条算出的 F1,真实值可能在哪个区间
用 numpy 计算分布
import numpy as np

delays = [0.8, 1.1, 1.0, 1.3, 0.9, 1.2, 9.5, 1.0, 1.1, 0.7, 8.2, 1.2]
arr = np.array(delays)
print("mean", round(arr.mean(), 2))      # 被长尾拉高的均值
print("p50 ", round(np.percentile(arr, 50), 2))
print("p95 ", round(np.percentile(arr, 95), 2))
print("std ", round(arr.std(), 2))

置信区间怎么理解

评估集只有 200 条时,F1=0.87 的 95% 置信区间可能宽达 ±0.05;样本量到 2000 条才会明显收窄。报告指标时附带区间,才能避免「0.87 比 0.85 高所以更好」这种误判。

07

评估样本要能代表真实分布

样本量与分层抽样

为什么不能随手抽 50 条

样本量太小,指标波动大、置信区间宽,任何「提升」都可能只是抽样噪声。而随机抽样只保证总体随机,不保证覆盖每个类别和风险桶——高风险的退款工单可能一条都没抽到。

分层抽样维度(智能客服)

分层维度原因建议
工单类别退款/物流/账号/咨询比例差异大每类至少 20~30 条,小类刻意多抽
难度简单问题掩盖复杂问题难样本单独一桶,指标分别计算
来源渠道App、网页、电话的话术和噪声不同按渠道比例抽样,或至少记录渠道
语言与方言不同语言回答质量差异明显覆盖主要语言,单独看指标

样本量经验

  • 做整体评估:200~500 条起步,能覆盖主要类别和常见失败。
  • 比较两个模型版本:按预期差异大小确定样本量,差异越小需要的样本越多。
  • 每类小样本(<30)的指标要标注「不稳定」,不参与上线对比。
评估集本身也是要版本化的测试资产:样本、标签、模型、Prompt 和阈值一起冻结,才谈得上「可回归、可对比」。
08

A/B 对比要区分真差异和噪声

显著性判断

场景:新旧模型对比

新模型在 300 条评估集上 F1=0.91,旧模型 F1=0.89。能不能说新模型更好?不能——如果样本是同一批、评估方式相同,2 个点的差距可能来自少量样本波动,需要看它是否显著。

判断差异是否可信

检查做法结论可信的条件
同一评估集新旧模型跑完全相同样本样本、标签、版本一致
置信区间分别算 F1 的 95% 区间区间不重叠,或差异大于合并误差
逐条对比配对查看哪些样本变了差异集中在可解释的样本上
稳定性多次重复运行看波动波动远小于两个版本的差距

显著性检验怎么用

连续指标(延迟、评分)可用配对 t 检验;分类正确与否可用 McNemar 检验比较两个模型在同一批样本上的差异。测试工程师至少要能读懂 p 值:p < 0.05 意味着「纯靠偶然得到这个差异的概率小于 5%」,但不能把 p 值当唯一依据——样本是不是有代表性、差异在业务上有没有意义,同样重要。

写对比结论的固定句式:在 X 条分层样本、同一评估流程下,新模型 F1 比旧模型高 Δ(95% CI: a~b),其中提升主要来自哪几类样本;先灰度到 5% 流量观察线上表现,再决定全量。
09

人工金标也要证明自己可靠

标注者一致性与 Kappa

问题:金标本身可能不一致

两位标注者对同一条回答,一个判「合格」一个判「不合格」。如果标注员之间都吵不清楚,拿什么当 Ground Truth 去评估模型?

Cohen's Kappa 手工计算
# 两位标注者对 100 条样本的分类结果
# observed agreement = 实际一致的比例
agreed = 82
total = 100
p_observed = agreed / total

# expected agreement = 偶然也会一致的比例(按双方各标签比例推算)
# 假设:A 判"合格"70 条、B 判"合格"76 条
pA = 70 / 100
pB = 76 / 100
p_expected = pA * pB + (1 - pA) * (1 - pB)

kappa = (p_observed - p_expected) / (1 - p_expected)
print("observed", p_observed, "expected", round(p_expected, 3))
print("kappa", round(kappa, 3))

Kappa 怎么解读

区间含义处理
< 0.2一致性差标注规范有问题,先修规范再标
0.2 ~ 0.4一般对分歧样本逐条讨论,明确边界
0.4 ~ 0.6中等可接受,但高风险桶要双人复核
0.6 ~ 0.8常规评估可用,分歧走仲裁
> 0.8很好金标可信,进入自动化回归

落地流程

  • 双人独立标注同一批样本,不互相看结果。
  • 计算 Kappa,分歧样本进入仲裁或标注规范修订。
  • 规范修订后重新标注分歧子集,确认 Kappa 提升。
  • 把标注规范、Kappa 值和仲裁记录随评估集一起版本化。
10

LLM Grader 也有系统性偏差

机器评审的陷阱

Grader 是什么

用另一个模型(LLM-as-a-Judge)给回答打分,是规模化评估的常用手段。但它不是中立仪器,会有一致的、可复现的偏差——这正是测试要抓的。

三类常见 Grader 偏差

偏差表现缓解手段
位置偏差列表里靠前的答案更容易得高分随机打乱候选顺序,多次取平均
长度偏差写得更长的答案得分更高限制输出长度,或按长度分层统计
自我偏好评审模型与自己同源的答案更宽容换一家评审模型交叉验证,关键样本人工复核

验证 Grader 是否可信

  • 抽取 50 条,让 Grader 和人工各自打分,计算一致性(Kappa)。
  • Grader 与人工一致性低的维度,不能自动放行,必须抽样人工复核。
  • 评审模型、评分 Prompt、打分维度都要版本化,和被测模型一样管理。
  • 资金、权限、隐私相关结论不做 Grader 自动放行。
Grader 偏差不解决,后面所有指标都是「评审模型的偏好」而不是「回答质量」。先把 Grader 校准好,再谈规模化评估。
11

模型版本对比要能给出上线结论

灰度、全量或回退

版本评估决策链

冻结评估集样本与版本
双跑打分新旧模型
分层看差异指标与最差样本
人工复核高风险桶
决策上线/灰度/回退

版本对比报告模板

区块内容决策依据
评估设置评估集版本、样本量、分层、阈值、Grader设置不同则不可比
总体指标新旧模型各指标与置信区间差异是否超过区间误差
按风险桶退款、高危、多语言等子集指标高风险桶不能回退
最差样本新模型明显变差的样本清单失败模式是否可解释、可拦截
成本与延迟Token、P95 延迟、调用次数质量提升是否值得成本增加

三种结论的写法

  • 上线:指标提升且置信区间不重叠,高风险桶无回退,人工复核通过。
  • 灰度:总体有提升但部分桶存疑,先 5% 流量观察线上告警与客诉。
  • 回退:关键桶明显变差或无法解释,保留旧版本并记录回退触发条件。
上线结论不是「新模型更好」,而是一份可复现的证据包:什么样本、什么指标、什么版本、谁复核、观察多久、什么条件下回退。
12

完成一套完整的评估闭环

练习与检查

练习:给智能客服做一个版本评估

  1. 从真实工单中按类别和难度分层抽取 100 条,记录每桶样本数。
  2. 双人独立标注 30 条,计算 Cohen's Kappa,低于 0.6 先修订规范。
  3. 在新旧模型上分别跑同一批样本,画混淆矩阵并计算每类 PRF。
  4. 报告均值、P95、置信区间,检查差异是否超过区间误差。
  5. 用 LLM Grader 打分后,与人工对比一致性;发现偏差则调整评审方式。
  6. 输出版本对比报告,给出上线、灰度或回退结论。

完成检查

能区分分类、回归、聚类及各自指标
会画并解读混淆矩阵
知道按业务代价选择 Precision/Recall/F1
能解释准确率为什么会被不平衡欺骗
报告指标时附带分布、P95 与置信区间
会用分层抽样构建评估样本
不把单次差异当结论,会做显著性判断
会计算并解读 Cohen's Kappa
知道 LLM Grader 的三类偏差及缓解
能给出一份可决策的上线/灰度/回退结论