机器学习模型评估工具--pr曲线和roc曲线
1.混淆矩阵
2.roc曲线原理
3.pr曲线原理
4.简单的代码实现
1.混淆矩阵
混淆矩阵(Confusion Matrix)是用于衡量分类算法效果的常用工具。它是一个二维表格,行表示实际类别,列表示预测类别,每一个表格元素表示预测为该类别的样本在实际上属于该类别的个数。
在二元分类问题中,混淆矩阵包含四个元素:真阳性(True Positive,TP)、假阳性(False Positive,FP)、真阴性(True Negative,TN)和假阴性(False Negative,FN),它们的定义如下:
- TP:实际为正类别的样本被预测为正类别的样本数;
- FP:实际为负类别的样本被预测为正类别的样本数;
- TN:实际为负类别的样本被预测为负类别的样本数;
- FN:实际为正类别的样本被预测为负类别的样本数。
真实类别/预测类别 | 正类别 | 负类别 |
---|---|---|
正类别 | TP | FN |
负类别 | FP | TN |
2.roc曲线原理
ROC曲线(Receiver Operating Characteristic curve)是一种用于评估二元分类器性能的常用工具。它以假阳性率(False Positive Rate,FPR)为横轴,真阳性率(True Positive Rate,TPR)为纵轴,绘制出的曲线。
真阳性率(TPR):也称为召回率(Recall),表示实际为正类别的样本中被正确预测为正类别的比例,计算公式为:TP / (TP + FN)。
假阳性率(FPR):表示实际为负类别的样本中被错误预测为正类别的比例,计算公式为:FP / (FP + TN)。
ROC曲线绘制
假设有如下数据:
样本编号 | 真实标签 | 预测概率 |
---|---|---|
1 | 正类 | 0.8 |
2 | 负类 | 0.4 |
3 | 正类 | 0.6 |
4 | 正类 | 0.7 |
5 | 负类 | 0.2 |
6 | 正类 | 0.3 |
7 | 负类 | 0.1 |
首先,按照预测概率对数据进行排序。从最小的概率开始,依次将每个样本作为正样本,计算对应的TPR和FPR,以此绘制ROC曲线。
阈值 | TP | FN | FP | TN | TPR | FPR |
---|---|---|---|---|---|---|
0 | 4 | 0 | 3 | 0 | 1.0 | 1.0 |
0.1 | 4 | 0 | 2 | 1 | 1.0 | 0.75 |
0.2 | 4 | 0 | 1 | 2 | 1.0 | 0.5 |
0.3 | 3 | 1 | 1 | 2 | 0.75 | 0.5 |
0.4 | 3 | 1 | 0 | 3 | 0.75 | 0.25 |
0.6 | 3 | 1 | 0 | 3 | 0.75 | 0.25 |
0.7 | 2 | 2 | 0 | 3 | 0.5 | 0.25 |
0.8 | 2 | 2 | 0 | 3 | 0.5 | 0.25 |
根据上表的数据,可以绘制出ROC曲线。横坐标为FPR,纵坐标为TPR。
3.pr曲线原理
PR曲线用于评估分类模型在不同阈值情况下的表现。PR代表Precision-Recall(精确度-召回率),该曲线绘制了分类器在不同召回率时对应的精确度。在二元分类问题中,精确度指被正确分类为正类别的样本数与被分类为正类别的所有样本数的比率,召回率指被正确分类为正类别的样本数与真实正类别样本总数的比率。
精确率(Precision):TP / (TP + FP),表示被分类器判定为正类的样本中真实为正类的比例。
召回率(Recall):TP / (TP + FN),表示真实为正类的样本中被分类器正确判定为正类的比例。
pr曲线绘制
在训练集上训练出二分类模型后我们将测试集中的数据输入模型,这时我们可以计算得到这些数据属于某个类别的概率,将这些预测概率从小到大排列,然后将分类阈值依次设为[0,1]区间中不同的概率值并计算这时的准确率和召回率,最后将这些准确率和召回率在二维坐标系中连起来就得到了pr曲线。按照roc曲线例子得出的曲线:
4.简单的代码实现
自己简单不调用库实现绘制
import numpy as np
import matplotlib.pyplot as plt
# 生成样本数据(假设y_true是真实标签,y_scores是分类器的分数)
np.random.seed(42)
y_true = np.random.randint(0, 2, size=100) # 随机生成0或1的真实标签
y_scores = np.random.rand(100) # 随机生成0到1之间的分类器分数
# 计算PR曲线
precision, recall, thresholds = [], [], sorted(y_scores, reverse=True)
positives_count, correct_positives_count = sum(y_true), 0
for threshold in thresholds:
predicted_positives = [int(score >= threshold) for score in y_scores]
true_positives = sum([int(t == 1 and p == 1) for t, p in zip(y_true, predicted_positives)])
precision.append(true_positives / sum(predicted_positives))
recall.append(true_positives / positives_count)
correct_positives_count += true_positives
# 计算ROC曲线
fpr, tpr = [], []
negatives_count, correct_negatives_count = len(y_true) - positives_count, 0
for threshold in thresholds:
predicted_positives = [int(score >= threshold) for score in y_scores]
true_positives = sum([int(t == 1 and p == 1) for t, p in zip(y_true, predicted_positives)])
false_positives = sum([int(t == 0 and p == 1) for t, p in zip(y_true, predicted_positives)])
tpr.append(true_positives / positives_count)
fpr.append(false_positives / negatives_count)
correct_positives_count += true_positives
correct_negatives_count += (len(y_true) - positives_count - false_positives)
# 计算AUC值
pr_auc = np.trapz(precision[::-1], recall[::-1]) # PR曲线下面积
roc_auc = np.trapz(tpr, fpr) # ROC曲线下面积
# 绘制PR曲线
plt.figure(figsize=(8, 6))
plt.plot(recall, precision, marker='o', linestyle='-', color='b')
plt.fill_between(recall, precision, alpha=0.2, color='b')
plt.xlabel('Recall')
plt.ylabel('Precision')
plt.title(f'PR Curve (AUC={pr_auc:.2f})')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.grid(True)
plt.show()
# 绘制ROC曲线
plt.figure(figsize=(8, 6))
plt.plot(fpr, tpr, marker='o', linestyle='-', color='b')
plt.plot([0, 1], [0, 1], linestyle='--', color='r')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title(f'ROC Curve (AUC={roc_auc:.2f})')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.grid(True)
plt.show()
这里没有用到大量的模型数据,只是简单的自己构造了一些标签和置信度,所以数据量很小,曲线并不平滑