混淆矩阵、精确率、召回率、F1值代码演示
1 课程概览
本课通过代码演示混淆矩阵、精确率、召回率、F1值的计算。回顾逻辑回归概念,详细讲解混淆矩阵的图解和计算方法,并通过10个样本的案例(6个恶性肿瘤为正例,4个良性为反例)演示模型A和模型B的评估。
2 核心概念与定义
- 逻辑回归:有监督学习,有特征有标签,标签离散,适用于二分类。
- 混淆矩阵:描述真实值和预测值之间关系的矩阵。
- 正例:默认使用分类少的充当正例。
- 精确率:真正例在预测正例中的占比。
- 召回率:真正例在真实正例中的占比。
- F1值:精确率和召回率的综合指标。
3 算法与模型详解
3.1 逻辑回归回顾
特点:
- 有监督学习
- 有特征,有标签
- 标签离散
- 适用于二分类
3.2 混淆矩阵图解
矩阵结构:
| 预测正例 | 预测反例 | |
|---|---|---|
| 真实正例 | TP(真正例) | FN(伪反例) |
| 真实反例 | FP(伪正例) | TN(真反例) |
术语:
| 缩写 | 全称 | 含义 |
|---|---|---|
| TP | True Positive | 真正例 |
| FN | False Negative | 伪反例 |
| FP | False Positive | 伪正例 |
| TN | True Negative | 真反例 |
单词:
- True:真
- False:假/伪
- Positive:正例
- Negative:反例
3.3 评估指标公式
精确率(Precision): $$\text{Precision} = \frac{TP}{TP + FP}$$
召回率(Recall): $$\text{Recall} = \frac{TP}{TP + FN}$$
F1值: $$F1 = \frac{2 \times \text{Precision} \times \text{Recall}}{\text{Precision} + \text{Recall}}$$
3.4 案例需求
数据:
- 10个样本
- 6个恶性肿瘤(正例)
- 4个良性肿瘤(反例)
模型A预测结果:
- 预测对了3个恶性肿瘤
- 预测对了4个良性肿瘤
模型B预测结果:
- 预测对了6个恶性肿瘤
- 预测对了1个良性肿瘤
3.5 模型A混淆矩阵
| 预测正例 | 预测反例 | |
|---|---|---|
| 真实正例(6) | TP=3 | FN=3 |
| 真实反例(4) | FP=0 | TN=4 |
计算:
- 精确率 = 3/(3+0) = 100%
- 召回率 = 3/(3+3) = 50%
- F1值 = 2×1×0.5/(1+0.5) = 66.7%
3.6 模型B混淆矩阵
| 预测正例 | 预测反例 | |
|---|---|---|
| 真实正例(6) | TP=6 | FN=0 |
| 真实反例(4) | FP=3 | TN=1 |
计算:
- 精确率 = 6/(6+3) = 66.7%
- 召回率 = 6/(6+0) = 100%
- F1值 = 2×0.667×1/(0.667+1) = 80%
4 数学原理与推导
4.1 混淆矩阵
$$\text{混淆矩阵} = \begin{bmatrix} TP & FN \ FP & TN \end{bmatrix}$$
4.2 精确率
$$\text{Precision} = \frac{TP}{TP + FP}$$
4.3 召回率
$$\text{Recall} = \frac{TP}{TP + FN}$$
4.4 F1值
$$F1 = \frac{2 \times \text{Precision} \times \text{Recall}}{\text{Precision} + \text{Recall}} = \frac{2TP}{2TP + FP + FN}$$
5 代码示例
import pandas as pd
from sklearn.metrics import (
confusion_matrix,
precision_score,
recall_score,
f1_score,
accuracy_score
)
# 1. 准备数据
# 10个样本:6个恶性肿瘤(正例,1),4个良性(反例,0)
y_true = [1, 1, 1, 1, 1, 1, 0, 0, 0, 0]
# 模型A预测结果:预测对3个恶性,4个良性
y_pred_A = [1, 1, 1, 0, 0, 0, 0, 0, 0, 0]
# 模型B预测结果:预测对6个恶性,1个良性
y_pred_B = [1, 1, 1, 1, 1, 1, 1, 1, 1, 0]
# 2. 计算混淆矩阵
print("=== 模型A ===")
cm_A = confusion_matrix(y_true, y_pred_A)
print("混淆矩阵:")
print(cm_A)
print("\n=== 模型B ===")
cm_B = confusion_matrix(y_true, y_pred_B)
print("混淆矩阵:")
print(cm_B)
# 3. 用DataFrame展示混淆矩阵
def show_confusion_matrix(y_true, y_pred, model_name):
"""用DataFrame展示混淆矩阵"""
cm = confusion_matrix(y_true, y_pred)
df = pd.DataFrame(
cm,
index=['真实良性(0)', '真实恶性(1)'],
columns=['预测良性(0)', '预测恶性(1)']
)
print(f"\n{model_name} 混淆矩阵:")
print(df)
show_confusion_matrix(y_true, y_pred_A, "模型A")
show_confusion_matrix(y_true, y_pred_B, "模型B")
# 4. 计算评估指标
def evaluate_model(y_true, y_pred, model_name):
"""评估模型"""
print(f"\n=== {model_name} 评估 ===")
# 混淆矩阵
cm = confusion_matrix(y_true, y_pred)
tn, fp, fn, tp = cm.ravel()
print(f"TP={tp}, FP={fp}, FN={fn}, TN={tn}")
print(f"准确率: {accuracy_score(y_true, y_pred):.4f}")
print(f"精确率: {precision_score(y_true, y_pred):.4f}")
print(f"召回率: {recall_score(y_true, y_pred):.4f}")
print(f"F1值: {f1_score(y_true, y_pred):.4f}")
# 评估两个模型
evaluate_model(y_true, y_pred_A, "模型A")
evaluate_model(y_true, y_pred_B, "模型B")
# 5. 手动计算验证
print("\n=== 手动计算验证 ===")
# 模型A
tp_A, fp_A, fn_A, tn_A = 3, 0, 3, 4
precision_A = tp_A / (tp_A + fp_A)
recall_A = tp_A / (tp_A + fn_A)
f1_A = 2 * precision_A * recall_A / (precision_A + recall_A)
print(f"模型A: 精确率={precision_A:.4f}, 召回率={recall_A:.4f}, F1值={f1_A:.4f}")
# 模型B
tp_B, fp_B, fn_B, tn_B = 6, 3, 0, 1
precision_B = tp_B / (tp_B + fp_B)
recall_B = tp_B / (tp_B + fn_B)
f1_B = 2 * precision_B * recall_B / (precision_B + recall_B)
print(f"模型B: 精确率={precision_B:.4f}, 召回率={recall_B:.4f}, F1值={f1_B:.4f}")
输出示例:
=== 模型A ===
混淆矩阵:
[[4 0]
[3 3]]
=== 模型B ===
混淆矩阵:
[[1 3]
[0 6]]
模型A 混淆矩阵:
预测良性(0) 预测恶性(1)
真实良性(0) 4 0
真实恶性(1) 3 3
模型B 混淆矩阵:
预测良性(0) 预测恶性(1)
真实良性(0) 1 3
真实恶性(1) 0 6
=== 模型A 评估 ===
TP=3, FP=0, FN=3, TN=4
准确率: 0.7000
精确率: 1.0000
召回率: 0.5000
F1值: 0.6667
=== 模型B 评估 ===
TP=6, FP=3, FN=0, TN=1
准确率: 0.7000
精确率: 0.6667
召回率: 1.0000
F1值: 0.8000
=== 手动计算验证 ===
模型A: 精确率=1.0000, 召回率=0.5000, F1值=0.6667
模型B: 精确率=0.6667, 召回率=1.0000, F1值=0.8000
6 重难点与易错提醒
- ❗重点:混淆矩阵的四个值(TP、FN、FP、TN)。
- ❗重点:精确率 = TP/(TP+FP),竖着看。
- ❗重点:召回率 = TP/(TP+FN),横着看。
- ❗重点:F1值综合考虑精确率和召回率。
- ❗重点:默认使用分类少的充当正例。
- ⚠️易错:混淆TP和FP的方向。
- ⚠️易错:混淆矩阵的行列顺序。
- 💡深入理解:模型A精确率高但召回率低,模型B召回率高但精确率低。
7 课堂问答精选
Q: 如何用代码计算混淆矩阵?
A: 使用sklearn.metrics的confusion_matrix函数:
from sklearn.metrics import confusion_matrix
cm = confusion_matrix(y_true, y_pred)
# 输出:[[TN, FP], [FN, TP]]
也可以用DataFrame展示更清晰:
df = pd.DataFrame(cm, index=['真实良性', '真实恶性'], columns=['预测良性', '预测恶性'])
Q: 模型A和模型B哪个更好?
A:
- 模型A:精确率100%,召回率50%,F1值66.7%
- 模型B:精确率66.7%,召回率100%,F1值80% 从F1值看,模型B更好。但具体选择取决于业务场景:如果注重不漏检(如癌症检测),选召回率高的模型B;如果注重准确性,选精确率高的模型A。
8 本课小结
- 混淆矩阵:描述真实值和预测值关系。
- 四个值:TP、FN、FP、TN。
- 精确率:TP/(TP+FP)。
- 召回率:TP/(TP+FN)。
- F1值:2×精确率×召回率/(精确率+召回率)。
- API:confusion_matrix、precision_score、recall_score、f1_score。
9 延伸思考与实践
- 实践:运行代码验证结果。
- 预习:混淆矩阵总结。
- 思考:如何根据业务场景选择评估指标?