用Python实战Kappa系数破解不平衡分类评估难题当你在医疗诊断数据集中看到模型对罕见病的预测准确率高达95%是否觉得可以开香槟庆祝了别急——这可能只是模型在作弊通过总是预测多数类来虚高指标。这正是传统准确率ACC在不平衡分类任务中的致命缺陷。本文将带你用Python实战两种更可靠的评估工具Cohens Kappa和二次加权KappaQWK并揭示何时该用哪个指标。1. 为什么准确率会说谎想象一个信用卡欺诈检测场景数据集中正常交易占99%欺诈交易仅1%。即使模型永远预测正常准确率也能达到99%。这种虚假繁荣背后是评估指标的严重失真。准确率的三大陷阱对类别分布极度敏感无法反映少数类的识别能力容易被懒惰模型钻空子from sklearn.metrics import accuracy_score import numpy as np # 模拟不平衡数据 y_true np.array([0]*990 [1]*10) # 99%负样本 y_pred np.zeros(1000) # 全部预测为负 print(f虚高的准确率: {accuracy_score(y_true, y_pred):.1%})输出结果会显示99%的准确率尽管模型完全没识别出欺诈交易。此时我们需要引入Kappa系数——它能惩罚这种投机取巧行为。其核心思想是扣除随机猜测带来的水分只保留模型真正的预测能力。2. Cohens Kappa系数实战2.1 计算原理拆解Kappa系数的计算公式看似简单$$ \kappa \frac{p_o - p_e}{1 - p_e} $$但每个成分都暗藏玄机$p_o$观察一致性即准确率$p_e$期望一致性随机猜测的基准from sklearn.metrics import cohen_kappa_score # 改进后的预测能识别部分欺诈 y_pred_improved np.array([0]*985 [1]*5 [0]*5 [1]*5) print(f原始Kappa: {cohen_kappa_score(y_true, y_pred):.3f}) print(f改进后Kappa: {cohen_kappa_score(y_true, y_pred_improved):.3f})你会看到尽管改进后的模型准确率降至99%但Kappa从0提升到0.333——真实反映了模型进步。2.2 结果解读指南Kappa值域为[-1, 1]通常解读为Kappa范围一致性程度≤0比随机猜测还差0.01~0.20极轻微一致0.21~0.40一般一致0.41~0.60中等一致0.61~0.80高度一致0.81~1.00几乎完全一致注意这些阈值并非绝对在高度不平衡数据中0.4的Kappa可能已经表现很好2.3 与其它指标对比我们用一个多分类示例对比常见指标from sklearn.metrics import classification_report y_true [0, 1, 2, 0, 1, 2, 0, 1, 2] y_pred [0, 1, 1, 0, 2, 1, 0, 1, 2] print(classification_report(y_true, y_pred)) print(fKappa: {cohen_kappa_score(y_true, y_pred):.3f})关键区别准确率忽略类别不平衡F1-score需要指定关注哪个类Kappa全局视角自动考虑随机概率3. 二次加权KappaQWK进阶当类别具有顺序关系时如电影评分1~5星普通Kappa的局限性显现了——它把所有的预测错误同等看待。而实际上预测3星实际4星的误差应该比预测1星实际5星小得多。3.1 QWK的加权哲学QWK通过引入二次权重矩阵对不同程度的错误区别对待$$ w_{i,j} \frac{(i-j)^2}{(N-1)^2} $$其中$i,j$分别是真实和预测的类别索引$N$是类别总数。def quadratic_weighted_kappa(y_true, y_pred): from sklearn.metrics import confusion_matrix cm confusion_matrix(y_true, y_pred) n_classes cm.shape[0] w np.zeros((n_classes, n_classes)) for i in range(n_classes): for j in range(n_classes): w[i][j] (i-j)**2 / (n_classes-1)**2 actual_hist np.sum(cm, axis1) pred_hist np.sum(cm, axis0) E np.outer(actual_hist, pred_hist) / np.sum(cm) O cm kappa 1 - np.sum(w * O) / np.sum(w * E) return kappa # 评分预测示例 true_ratings [1, 2, 3, 4, 5, 4, 3, 2, 1] pred_ratings [1, 2, 3, 5, 4, 4, 3, 3, 2] print(f普通Kappa: {cohen_kappa_score(true_ratings, pred_ratings):.3f}) print(fQWK: {quadratic_weighted_kappa(true_ratings, pred_ratings):.3f})3.2 业务场景选择指南场景特征推荐指标原因类别无序且平衡ACC/F1简单直观类别无序但不平衡Cohens Kappa惩罚随机猜测类别有序评级、评分QWK考虑错误程度差异需要类别特异性分析混淆矩阵F1提供细粒度洞察4. 实战案例糖尿病预测模型评估让我们用真实场景综合运用这些指标。假设我们有一个糖尿病预测数据集阳性样本占8%from sklearn.datasets import make_classification from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import train_test_split # 生成不平衡数据 X, y make_classification(n_samples1000, n_classes2, weights[0.92, 0.08], random_state42) X_train, X_test, y_train, y_test train_test_split(X, y, test_size0.2, random_state42) # 训练模型 model RandomForestClassifier(random_state42) model.fit(X_train, y_train) y_pred model.predict(X_test) # 综合评估 print(f准确率: {accuracy_score(y_test, y_pred):.3f}) print(fCohens Kappa: {cohen_kappa_score(y_test, y_pred):.3f}) print(fF1-score: {f1_score(y_test, y_pred):.3f}) # 生成概率预测用于AUC y_probs model.predict_proba(X_test)[:, 1] print(fROC-AUC: {roc_auc_score(y_test, y_probs):.3f})典型输出可能显示准确率0.94看似很高Kappa 0.55揭示真实性能F1-score 0.60关注阳性类AUC 0.92概率预测质量关键洞见当Kappa与准确率差异大时说明数据不平衡在扭曲评估Kappa与F1结合可以全面判断模型表现AUC提供额外的概率预测质量信息在模型迭代过程中我习惯监控Kappa和F1的组合变化。曾有个医疗项目准确率提升0.5%时Kappa却下降了3%——深入分析发现模型在少数类上出现了性能退化这个信号帮我们及时调整了采样策略。