分类模型错在哪?用混淆矩阵导出误分类样本并回查原始编号

将真值、预测和稳定编号逐行对应,核对混淆矩阵并导出误分类 CSV,区分误报漏报和标注问题。

准确率或 F1 能概括模型表现,却不能告诉你究竟哪些样本出了错。实际排查需要将预测、真值和原始编号逐行对应,区分误报和漏报,再把错误行交给人复核。这里用混淆矩阵核对错误计数,并导出包含原文和编号的 CSV。

先固定正类和编号

示例任务是判断客服反馈是否需要人工跟进:1 表示需要,0 表示不需要。以下八条文本、编号、真值和预测均为虚构,用来演示错误定位,未训练客服模型。接入真实数据时,预测和真值必须来自同一批样本,不能分别排序后直接拼接。

分类模型错在哪?用混淆矩阵导出误分类样本并回查原始编号

优先沿用采集时的稳定编号。若编号重复,先查明是否多版本、重复采集或标签冲突;不要临时用行号掩盖问题。文本若含个人资料,应在本地有权限的环境复核,导出文件也要遵循原数据的使用范围。

计算矩阵并导出错误行

以下示例在 Python 3.11、scikit-learn 1.7.2 的独立环境运行通过。先在练习目录创建虚拟环境并安装对应版本:

python -m venv .venv
# Windows PowerShell
.\.venv\Scripts\python.exe -m pip install "scikit-learn==1.7.2"
# 以下脚本统一用该环境的 Python 运行,例如:
.\.venv\Scripts\python.exe demo.py
import csv
from collections import Counter
from sklearn.metrics import confusion_matrix, classification_report

# 以下标签、编号及文本都是虚构的,模拟模型预测表的导出结果。
ids = [f"demo-{i:02d}" for i in range(8)]
texts = ["没有问题", "等待太久", "退款未到", "处理完成",
         "无法登录", "谢谢解答", "商品损坏", "收不到短信"]
truth = [0, 1, 1, 0, 1, 0, 1, 1]  # 1 表示需要人工跟进
prediction = [0, 1, 0, 0, 1, 1, 1, 0]
if not (len(ids) == len(texts) == len(truth) == len(prediction)):
    raise ValueError("编号、原文、真值和预测必须逐行对应")
if len(set(ids)) != len(ids) or set(truth + prediction) - {0, 1}:
    raise ValueError("编号重复或标签不符合 0/1 约定")
matrix = confusion_matrix(truth, prediction, labels=[0, 1])
tn, fp, fn, tp = matrix.ravel()
errors = []
for rid, text, actual, predicted in zip(ids, texts, truth, prediction):
    if actual != predicted:
        errors.append({"id":rid, "text":text, "truth":actual,
                       "prediction":predicted, "error_type":"FP" if predicted == 1 else "FN"})
assert int(matrix.sum()) == len(ids)
assert len(errors) == int(fp + fn)
with open("misclassified.csv", "w", encoding="utf-8-sig", newline="") as f:
    writer = csv.DictWriter(f, fieldnames=["id","text","truth","prediction","error_type"])
    writer.writeheader()
    writer.writerows(errors)
print("矩阵(行=真值,列=预测)", matrix.tolist())
print("TN FP FN TP", int(tn), int(fp), int(fn), int(tp))
print("误分类编号", [r["id"] for r in errors])
print("错误类型", dict(Counter(r["error_type"] for r in errors)))
print(classification_report(truth, prediction, labels=[0,1], zero_division=0))

当前环境输出:

矩阵(行=真值,列=预测) [[2, 1], [2, 3]]
TN FP FN TP 2 1 2 3
误分类编号 ['demo-02', 'demo-05', 'demo-07']
错误类型 {'FN': 2, 'FP': 1}
              precision    recall  f1-score   support

           0       0.50      0.67      0.57         3
           1       0.75      0.60      0.67         5

    accuracy                           0.62         8
   macro avg       0.62      0.63      0.62         8
weighted avg       0.66      0.62      0.63         8

labels=[0,1] 固定矩阵顺序:行是真值,列是预测。左上为 TN,右上为 FP,左下为 FN,右下为 TP。本例 FP=1、FN=2,错误行共 3 条;导出的编号为 demo-02、demo-05、demo-07。断言要求矩阵总数等于样本数,CSV 错误行数等于 FP+FN。

怎样回查与记录原因

打开脚本运行目录中的 misclassified.csv。先按 id 找原始记录,再查看真值是如何产生的;“标签错误”与“模型没学会”需要不同修复。建议另外添加 review_reason 列,使用明确的原因,例如“人工真值需修订”“上下文缺失”“否定词误判”“业务标签定义含糊”,保留复核人和日期。

本例 demo-05 被预测为需要跟进,是误报;demo-02 与 demo-07 被预测为不需要,是漏报。它们说明错误类型的定位方法,不能据此推断某个真实模型存在相同缺陷。若补充上下文才能判断,将样本标为待复核,不能为了提高分数直接改成模型的预测。

排查后如何继续

用于开发的验证集可以帮助发现问题、修订标注规范并训练下一版;需要记录每次改动,再用保持独立的数据评估。最终测试集一旦被反复查看并用于改参数,就已参与开发,原来的测试分数不能继续作为一次独立检验。

多分类的混淆矩阵不再能直接 ravel 成四个数字。应固定全量类别顺序,按实际类别对查看混淆;某类没有预测样本时,zero_division=0 让报告输出零,但这不是该类表现良好的证据。长度不同、标签映射冲突或原始编号缺失时应先停止分析。

相关问答与依据

误报和漏报哪个更严重?由业务代价决定。漏掉必须人工跟进的投诉可能更严重,但不能替所有任务统一判断;先列明漏报成本和误报处理容量,再决定优化目标。

依据:confusion_matrix 官方文档规定行列含义和 labels 顺序;classification_report 文档说明逐类指标与零除处理。代码实际验证的是虚构列表的计数和导出一致性,没有证明模型达到上线标准。

Ai菜鸟网。发布者:AI小管家,转载请注明出处:https://www.alyyhw.com/30111.html

赞 (0)
AI小管家的头像AI小管家
标准化为什么会造成数据泄漏?用 scikit-learn Pipeline 只拟合训练集
上一篇 10小时前
逻辑回归和随机森林怎么选?在同一划分下比较 Macro F1 与训练时间
下一篇 10小时前

相关推荐

联系我们

联系我们

1

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信
关注微信
分享本页
返回顶部