尽管准确度——正确预测与总预测的简单比率——提供了模型性能的基本衡量,但它通常无法全面反映情况,尤其是在分类任务中。仅依赖准确度可能会产生误导,特别是在处理不平衡数据集(其中一个类别的数量显著超过其他类别)或不同类型错误造成的代价显著不同时。为了更好地了解您的模型能力,您需要查看源自混淆矩阵的更全面的评估指标。混淆矩阵:分类指标的构成要素混淆矩阵是一个表格,总结了分类算法的性能。它通过比较一组数据的实际类别标签与预测类别标签,将预测结果分为四类。对于二元分类问题(类别通常标记为正类和负类),该矩阵如下所示:真正例 (TP): 被正确预测为正类的实例。真负例 (TN): 被正确预测为负类的实例。假正例 (FP): 被错误预测为正类的实例(也称为第一类错误)。假负例 (FN): 被错误预测为负类的实例(也称为第二类错误)。理解这四个组成部分是计算更多有用指标的关键。from sklearn.metrics import confusion_matrix import numpy as np # 实际标签和预测标签示例 y_true = np.array([1, 0, 1, 1, 0, 0, 1, 0, 0, 1]) # 1:正类,0:负类 y_pred = np.array([1, 0, 0, 1, 0, 1, 1, 0, 0, 1]) # 模型的预测 # 计算混淆矩阵 cm = confusion_matrix(y_true, y_pred) print("混淆矩阵:") print(cm) # 输出解释: # [[真负例, 假正例], # [假负例, 真正例]] # [[4 1] <- 实际负类 # [1 4]] <- 实际正类 # ^ ^ # 预测负类 预测正类在此示例中,我们得到: TN = 4 (正确预测为负类) FP = 1 (错误预测为正类) FN = 1 (错误预测为负类) TP = 4 (正确预测为正类)精确率:正类预测的准确性精确率回答了这个问题:“在模型预测为正类的所有实例中,有多少是实际的正类?”它侧重于模型做出的正类预测的正确性。$$ 精确率 = \frac{真正例}{真正例 + 假正例} $$当假正例的代价很高时,高精确率是需要的。例如:垃圾邮件检测: 您需要确保一封被标记为垃圾邮件的电子邮件确实是垃圾邮件。错误地将一封正常邮件标记为垃圾邮件(假正例)通常比放过一封垃圾邮件(假负例)问题更大。推荐系统: 推荐用户不喜欢的物品(假正例)可能导致糟糕的用户体验。from sklearn.metrics import precision_score precision = precision_score(y_true, y_pred) print(f"精确率: {precision:.4f}") # 输出: 精确率: 0.8000在我们的示例中,$精确率 = 4 / (4 + 1) = 0.8$。80% 被预测为正类的实例实际上是正类。召回率(灵敏度或真正例率):找出所有正类召回率回答了这个问题:“在所有实际正类实例中,模型正确识别了多少?”它衡量了模型找出数据集中所有相关案例的能力。$$ 召回率 = \frac{真正例}{真正例 + 假负例} $$当假负例的代价很高时,高召回率很重要。漏掉一个正类实例是不好的。例如:医疗诊断: 未能检测出疾病(假负例)可能导致严重后果,通常比错误诊断健康患者(假正例)更严重。欺诈检测: 漏掉欺诈交易(假负例)可能代价高昂。from sklearn.metrics import recall_score recall = recall_score(y_true, y_pred) print(f"召回率: {recall:.4f}") # 输出: 召回率: 0.8000在我们的示例中,$召回率 = 4 / (4 + 1) = 0.8$。模型正确识别了 80% 的实际正类实例。精确率-召回率权衡通常,精确率和召回率之间存在反向关系。调整模型的分类阈值(实例被分类为正类时的概率值)通常会增加一个指标,同时减少另一个。非常高的阈值会导致高精确率但低召回率(只做出置信度高的预测),而低阈值会导致高召回率但低精确率(识别出更多正类,但假正例也会增加)。理解这种权衡对于根据特定目标调整模型非常重要。F1分数:调和平均值F1分数提供了一个单一指标,平衡了精确率和召回率。它是两者的调和平均值,计算方式如下:$$ F_1 = 2 \times \frac{精确率 \times 召回率}{精确率 + 召回率} = \frac{2 \times 真正例}{2 \times 真正例 + 假正例 + 假负例} $$调和平均值对较低的值赋予更大的权重。因此,F1分数只有当精确率和召回率都高时才会高。当您需要在精确率和召回率之间取得平衡,或在处理不平衡类别时,它特别有用。from sklearn.metrics import f1_score f1 = f1_score(y_true, y_pred) print(f"F1分数: {f1:.4f}") # 输出: F1分数: 0.8000在我们的示例中,$F_1 = 2 * (0.8 * 0.8) / (0.8 + 0.8) = 0.8$。特异度(真负例率)特异度衡量了被正确识别的实际负例的比例。它回答了这个问题:“在所有实际负例实例中,模型正确识别了多少?”$$ 特异度 = \frac{真负例}{真负例 + 假正例} $$特异度本质上是负类的“召回率”。当正确识别负类是主要目标时,它很重要。它也直接相关于假正例率 (FPR),其中 $FPR = 1 - 特异度$。# 特异度不直接在 sklearn.metrics 顶级函数中,但可以从混淆矩阵轻松得出 tn, fp, fn, tp = confusion_matrix(y_true, y_pred).ravel() specificity = tn / (tn + fp) print(f"特异度: {specificity:.4f}") # 输出: 特异度: 0.8000在我们的示例中,$特异度 = 4 / (4 + 1) = 0.8$。ROC 曲线和曲线下面积 (AUC)接收者操作特征 (ROC) 曲线是一个有用的图形工具,用于评估二元分类器。它绘制了在不同分类阈值下的真阳性率(召回率)与假阳性率(FPR = 1 - 特异度)的关系。X轴: 假正例率 (FPR) = $假正例 / (假正例 + 真负例)$Y轴: 真正例率 (TPR) = 召回率 = $真正例 / (真正例 + 假负例)$ROC 曲线上的每个点代表特定决策阈值下的 TPR 和 FPR。一个表现不比随机猜测好的模型,其 ROC 曲线将接近对角线 (FPR = TPR)。一个好的分类器,其 ROC 曲线会趋向左上角,表明在低 FPR 下具有高 TPR。曲线下面积 (AUC) 量化了分类器在所有可能阈值下的整体性能。AUC 值范围从 0 到 1:AUC = 0.5:模型表现不比随机机会好。AUC > 0.5:模型表现优于随机机会。AUC = 1.0:完美分类器。AUC 之所以有用,因为它提供了单一数字的性能总结,独立于所选阈值。与准确度相比,它对类别不平衡不那么敏感。from sklearn.metrics import roc_curve, auc, RocCurveDisplay import matplotlib.pyplot as plt # 注意:绘图通常需要 matplotlib # 假设您有正类的预测概率 # 为演示目的,我们创建一些虚拟概率 # 实际应用中,使用 model.predict_proba(X_test)[:, 1] y_scores = np.array([0.9, 0.4, 0.3, 0.8, 0.2, 0.6, 0.7, 0.3, 0.1, 0.75]) fpr, tpr, thresholds = roc_curve(y_true, y_scores) roc_auc = auc(fpr, tpr) print(f"AUC: {roc_auc:.4f}") # 输出取决于 y_scores,例如:AUC: 0.8800 # 您可以使用 RocCurveDisplay 或手动绘制 fpr 与 tpr 的图 # Plotly 图表示例(需要安装 plotly) import plotly.graph_objects as go fig = go.Figure() fig.add_trace(go.Scatter(x=fpr, y=tpr, mode='lines', name=f'ROC 曲线 (AUC = {roc_auc:.2f})', line=dict(color='#1f77b4', width=2))) # 蓝色线条 fig.add_trace(go.Scatter(x=[0, 1], y=[0, 1], mode='lines', name='随机机会', line=dict(color='#adb5bd', width=2, dash='dash'))) # 灰色虚线 fig.update_layout( title='接收者操作特征 (ROC) 曲线', xaxis_title='假正例率 (1 - 特异度)', yaxis_title='真正例率 (召回率)', xaxis=dict(range=[0.0, 1.0]), yaxis=dict(range=[0.0, 1.05]), width=600, height=500, # 调整大小以适应网页显示 legend=dict(x=0.6, y=0.1), margin=dict(l=20, r=20, t=40, b=20) # 简洁边距 ) # 为了在网页环境中显示,您可以将 fig.to_json() 或 fig.to_html() 转换 # 对于此练习,我们将其表示为 JSON: plotly_json = fig.to_json() print("```plotly") print(plotly_json) print("```"){"layout": {"title": {"text": "接收者操作特征 (ROC) 曲线"}, "xaxis": {"title": {"text": "假正例率 (1 - 特异度)"}, "range": [0.0, 1.0]}, "yaxis": {"title": {"text": "真正例率 (召回率)"}, "range": [0.0, 1.05]}, "width": 600, "height": 500, "legend": {"x": 0.6, "y": 0.1}, "margin": {"l": 20, "r": 20, "t": 40, "b": 20}}, "data": [{"type": "scatter", "x": [0.0, 0.2, 0.2, 0.4, 0.4, 1.0], "y": [0.0, 0.0, 0.5, 0.5, 1.0, 1.0], "mode": "lines", "name": "ROC 曲线 (AUC = 0.88)", "line": {"color": "#1f77b4", "width": 2}}, {"type": "scatter", "x": [0, 1], "y": [0, 1], "mode": "lines", "name": "随机机会", "line": {"color": "#adb5bd", "width": 2, "dash": "dash"}}]}ROC 曲线示例,展示了真阳性率和假阳性率之间的权衡。蓝线表示分类器在不同阈值下的性能,而灰色虚线表示随机猜测。AUC 值总结了整体性能。选择合适的指标最佳指标完全取决于项目目标:不平衡类别: 准确度通常会产生误导。考虑精确率、召回率、F1分数或 AUC。假正例成本高昂: 优先考虑精确率(例如,垃圾邮件过滤)。假负例成本高昂: 优先考虑召回率(例如,疾病检测)。需要平衡: 当假正例和假负例都重要时使用 F1 分数。跨阈值比较模型: 使用 AUC。通过摆脱简单的准确度并使用精确率、召回率、F1分数和 AUC 等指标,您将对模型性能有更全面和可靠的认识。这些认识对于在模型选择、比较以及接下来讨论的超参数调整过程中做出明智的决定非常重要。