1.分类模型评估指标—精准率、召回率、ROC曲线
所有事情都需要评估好坏,尤其是量化的评估指标
机器学习有很多评估的指标。有了这些指标我们就横向的比较哪些模型的表现更好。我们先从整体上来看看主流的评估指标都有哪些:
准确率 – Accuracy 精确率(差准率)- Precision
召回率(查全率)- Recall F1分数 ROC曲线 AUC曲线
为了方便理解对分类问题进行图解
我们有10张照片,5张男性、5张女性。如下图
一个判断性别的机器学习模型,当我们使用它来判断“是否为男性”时,会出现4种情况
男性为正样本,女性为负样本
1.实际为男性,预测为男性 TP – True Positive
2.实际为女性,错误地预测为男性 FP – False Positive
3.实际为男性,错误地预测为女性 FN – False Negative
4.实际为女性,预测为女性 TN – True Negative
1.1 准确率-Accuracy
预测正确的结果占总样本的百分比,公式如下:
1.2 精确率(差准率)- Precision
所有被预测为正的样本中实际为正的样本的概率,公式如下:实际为正的样本中被预测为正样本的概率,其公式如下
1.3 召回率(查全率)- Recall
实际为正的样本中被预测为正样本的概率,其公式如下
召回率越高,代表实际坏用户被预测出来的概率越高
1.4 PR曲线
如果我们把精确率(Precision)和召回率(Recall)之间的关系用图来表达,就是下面的PR曲线
PR曲线:PR曲线是一个用于评估二元分类问题的工具。它绘制了模型预测的精确度(Precision)和召回率(Recall)之间的关系。曲线的x轴表示Recall,y轴表示Precision。理想的PR曲线应该尽可能地接近右上角,这意味着模型在保持高召回率的同时,也能保持高精确度。
1.5 F1分数
为了综合两者的表现,在两者之间找一个平衡点,就出现了一个 F1分数。
1.6 ROC曲线
ROC(Receiver Operating Characteristic)曲线,又称接受者操作特征曲线。该曲线最早应用于雷达信号检测领域,用于区分信号与噪声。后来人们将其用于评价模型的预测能力,ROC 曲线是基于混淆矩阵得出的。
ROC 曲线中的主要两个指标就是真正率和假正率, 上面也解释了这么选择的好处所在。其中横坐标为假正率(FPR),纵坐标为真正率(TPR),下面就是一个标准的 ROC 曲线图。
真正率(TPR) = 灵敏度 = TP/(TP+FN)
假正率(FPR) = 1- 特异度 = FP/(FP+TN)
参考一文看懂机器学习指标:准确率、精准率、召回率、F1、ROC曲线、AUC曲线
2.实现
对鸢尾花的分类进行评估
文件鸢尾花分类
链接:https://pan.baidu.com/s/11lHWBdgBlzm9H7iBYlFxJQ
提取码:6666
# 绘制P-R曲线(精确率-召回率曲线)
print(__doc__)
# 绘制P-R曲线(精确率-召回率曲线)
# plt:绘图
import matplotlib.pyplot as plt
# np:处理矩阵运算
import numpy as np
# svm:支持向量机
# datasets:数据集模块 后续使用该模块导入"鸢尾花数据集"
from sklearn import svm, datasets
# precision_recall_curve:精确率-召回率曲线
from sklearn.metrics import precision_recall_curve
# average_precision_score:根据预测分数计算平均精度(AP)
from sklearn.metrics import average_precision_score
# train_test_split:训练集与测试集的拆分模块
from sklearn.model_selection import train_test_split
# label_binarize:标签的二处理
from sklearn.preprocessing import label_binarize
# OneVsRestClassifier:一对其余 每次将某一类作为正类 其余作为负类
from sklearn.multiclass import OneVsRestClassifier
# 导入鸢尾花数据集
iris = datasets.load_iris()
# x为数据集的样本特征矩阵 150*4
x = iris.data
# y是类别标签矩阵 150*1
y = iris.target
y
[[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 1 0]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]
[0 0 1]]
# Add noisy features 增加了800维的噪声特征
random_state = np.random.RandomState(0)
n_samples, n_features = x.shape
# n_samples=150 n_features=4
(150, 4)
# 在150×4的矩阵后增加了150*800的矩阵
x = np.c_[x, random_state.randn(n_samples, 200*n_features)]
# 进行训练集与测试集的拆分 比例为0.5
x_train, x_test, y_train, y_test = train_test_split(x,y,test_size=.5,random_state = random_state)
# 构建分类器 进行二类问题的转化
classifier = OneVsRestClassifier(svm.SVC(kernel='linear',probability=True,random_state=random_state))
# 利用训练集进行拟合 并将测试集传入获取对测试集中y值的预测
y_score = classifier.fit(x_train,y_train).decision_function(x_test)
# 将y_score这个预测值与每个样本的真实值进行比较
precision = dict()
recall = dict()
average_precision = dict()
for i in range(n_classes):
#下划线是返回的阈值。作为一个名称:此时“_”作为临时性的名称使用。
#表示分配了一个特定的名称,但是并不会在后面再次用到该名称。
precision[i], recall[i],_ = precision_recall_curve(y_test[:,i],y_score[:,i])
average_precision[i] = average_precision_score(y_test[:,i],y_score[:,i])
# 切片 第i个类的分类结果性能
# Compute micro-average curve and area. ravel()将多维数组降为一维
precision['micro'],recall['micro'],_ = precision_recall_curve(y_test.ravel(),y_score.ravel())
average_precision['micro'] = average_precision_score(y_test, y_score, average='micro')
plt.clf()# 清楚当前图像窗口
plt.plot(recall['micro'],precision['micro'],label='micro-average Precision-recall curve (area ={0:0.2f})'.format(average_precision['micro']))
for i in range(n_classes):
plt.plot(recall[i], precision[i], label='Precision recall curve of class {0} (area = {1:0.2f})'.format(i,average_precision[i]))
#调整刻度范围
plt.xlim([0.0,1.0])
plt.ylim([0.0,1.05])
# 横纵坐标
plt.xlabel('Recall',fontsize=16)
plt.ylabel('Precision',fontsize=16)
# 图像名称 图例
plt.title('Extension of Precision-Recall curve to multi-class',fontsize=16)
plt.legend(loc="lower right")
plt.show()
3.小结
模型的精确度和召回率互相制约,P-R曲线越向右上凸,表示模型性能越好。
这里特指负样本数量远大于正样本时,在这类问题中,我们往往更关注正样本是否被正确分类,即TP的值。PR曲线更适合度量类别不平衡问题中:
因为在PR曲线中TPR和FPR的计算都会关注TP,PR曲线对正样本更敏感。
而ROC曲线正样本和负样本一视同仁,在类别不平衡时ROC曲线往往会给出一个乐观的结果。