博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
机器学习之分类结果的评价
阅读量:7120 次
发布时间:2019-06-28

本文共 5854 字,大约阅读时间需要 19 分钟。

以逻辑回归为例,介绍分类结果的评价方式。

精准率和召回率

对于极度偏斜的数据,使用分类准确度来评判模型的好坏是不恰当的,精确度和召回率是两个更好的指标来帮助我们判定模型的好快。

二分类的混淆矩阵

精准率和召回率是存在于混淆矩阵之上的,以二分类为例,分类0是偏斜数据中占优势的一方,将关注的重点放在分类为1上,其混淆矩阵如下:

真实值预测值 0 1
0 9978(TN) 12(FP)
1 2(FN) 8(TP)
  1. TN 的含义是预测 negative 正确的数量,即真实分类为0预测的分类结果也为0的共有9978个;
  2. FN 的含义是预测 negative 错误的数量,即真实分类为1预测的分类结果为0的共有2个;
  3. FP 的含义是预测 positive 错误的数量,即真实分类为0预测的分类结果为1的共有12个;
  4. TP 的含义是预测 positive 正确的数量,即真实分类为1预测的分类结果也为1的共有8个。

TN、FN、FP、TP 的实现如下(y_true 表示真实分类, y_predict 表示预测结果):

import numpy as npdef TN(y_true, y_predict):    return np.sum((y_true == 0) & (y_predict == 0))def FP(y_true, y_predict):    return np.sum((y_true == 0) & (y_predict == 1))def FN(y_true, y_predict):    return np.sum((y_true == 1) & (y_predict == 0))def TP(y_true, y_predict):    return np.sum((y_true == 1) & (y_predict == 1))

混淆矩阵的结果为:

def confusion_matrix(y_test, y_predict):    return np.array([        [TN(y_test, y_log_predict), FP(y_test, y_log_predict)],        [FN(y_test, y_log_predict), TP(y_test, y_log_predict)]    ])

Scikit Learn 中封装了混淆矩阵方法 confusion_matrix()

from sklearn.metrics import confusion_matrixconfusion_matrix(y_true, y_predict)

精准率和召回率及实现

有了混淆矩阵,精准率和召回率久很好表示了。

精准率表示预测分类结果中预测正确的数量的占比,即:

$$ precision=\frac{TP}{TP+FP} $$

将其用代码表示为:

def precision_score(y_true, y_predict):    tp = TP(y_true, y_predict)    fp = FP(y_true, y_predict)    try:        return tp / (tp + fp)    except:        return 0.0

召回率表示真实分类中被预测正确的数量的占比,即:

$$ recall=\frac{TP}{TP+FN} $$

将其用代码表示为:

def recall_score(y_true, y_predict):    tp = TP(y_true, y_predict)    fn = FN(y_true, y_predict)    try:        return tp / (tp + fn)    except:        return 0.0

Scikit Learn 中也封装了计算精准率的方法 precision_score() 和计算召回率的方法 recall_score()

from sklearn.metrics import precision_scoreprecision_score(y_true, y_predict)from sklearn.metrics import recall_scorerecall_score(y_true, y_predict)

F1 Score

精准率和召回率这两个指标的侧重点不同,有的时候我们注重精准率(如股票预测),有的时候我们注重召回率(病人诊断)。但有时候又需要把两者都考虑进行,此后就可以使用 F1 Score 指标。

F1 Score 是精准率和召回率的调和平均值,公式为:

$$ \frac{1}{F1}=\frac{1}{2}(\frac{1}{precision}+\frac{1}{recall}) $$

即:$F1=\frac{2·precision·recall}{precesion+recall}$,并且 F1 Score 的取值是在区间 $[0, 1]$ 之中的。

代码实现为:

def f1_score(y_true, y_predict):    precision = precision_score(y_true, y_predict)    recall = recall_score(y_true, y_predict)    try:        return 2 * precision * recall / (precision + recall)    except:        return 0.0

Scikit Learn 中封装了方法 f1_score() 来计算 F1 Score:

from sklearn.metrics import f1_scoref1_score(y_true, y_predict)

Precision-Recall 曲线

Scikit Learn 的逻辑回归中的概率公式为 $\hat p=\sigma(\theta^T·x_b)$ ,其决策边界为 $\theta^T·x_b=0$,但是如果决策边界不为0会如何呢?

假定决策边界为 $\theta^T·x_b=threshold$,当 threshold 的取值不同(0、大于0的某个值、小于0的某个值),对应的精确度和召回率也不同。如图:

clipboard.png

圆形和星形是不同的的分类,并且重点放在星形的分类上,可以看出,threshold 的取值越大时,精确率越高,而召回率越低。

如果要更改决策边界,逻辑回归的 decision_function() 返回传入数据的 $\theta^T·x_b$ 计算结果 decision_scores,接着再构建一个新的预测结果;如代码所示,设定 decision_scores >= 5(默认decision_scores >= 0 ) 的预测结果才为1,其余为0:

from sklearn.linear_model import LogisticRegressionlog_reg = LogisticRegression()# X_train, y_train 为训练数据集log_reg.fit(X_train, y_train)# X_test,y_test 为测试数据集decision_scores = log_reg.decision_function(X_test)y_log_predict_threshold = np.array(decision_scores >= 5, dtype='int')

如此可以得到不同的 y_log_predict_threshold,进而得到不同的精准率和召回率。

以手写数字识别数据为例,将标记为9的数据分类为1,其余分类为0:

from sklearn import datasetsdigits = datasets.load_digits()X = digits.datay = digits.target.copy()y[digits.target==9] = 1y[digits.target!=9] = 0from sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(X, y, random_state=500)

接着训练逻辑回归模型:

from sklearn.linear_model import LogisticRegressionlog_reg = LogisticRegression()log_reg.fit(X_train, y_train)

获取测试数据集 X_test 对应的 $\theta^T·x_b$ 取值:

decision_scores = log_reg.decision_function(X_test)

在 decision_scores 的取值区间划分为一系列值 thresholds ,并将其中的值依次作为决策边界,进而得到不同的精确率和召回率

from sklearn.metrics import precision_scorefrom sklearn.metrics import recall_scoreprecisions = []recalls = []thresholds = np.arange(np.min(decision_scores), np.max(decision_scores), 0.1)for threshold in thresholds:    y_predict = np.array(decision_scores >= threshold, dtype='int')    precisions.append(precision_score(y_test, y_predict))    recalls.append(recall_score(y_test, y_predict))

将精确率、召回率与决策边界的关系绘制如图:

clipboard.png

精确度与召回率的关系,即 Precision-Recall 曲线则为:

clipboard.png

Scikit Learn 中提供的 precision_recall_curve() 方法传入真实分类结果和 decision_scores,返回 precisions、recalls 和 thresholds:

from sklearn.metrics import precision_recall_curveprecisions, recalls, thresholds = precision_recall_curve(y_test, decision_scores)

Precision-Recall 曲线越靠外(即面积越大)则表示模型越好。

多分类中的精确率和召回率

在过分类中,Sckit Learn 提供的 confusion_matrix() 可以直接返回多分类的混淆矩阵,而对于精确率和召回率,则要在 Sckit Learn 提供的方法中指定 average 参数值为 micro,如:

from sklearn.metrics import precision_scoreprecision_score(y_test, y_predict, average='micro')

ROC 曲线

对于用图形面积判断模型好快,ROC 曲线比 Precision-Recall 曲线要好。

ROC 曲线涉及两个指标,TPR 和 FPR。TPR 就是召回率,即:$TPR=\frac{TP}{TP+FN}$;FPR 表示真实分类(偏斜数据中占优势的分类)中被预测错误的数量的占比,即:$FPR=\frac{FP}{TN+FP}$。实现代码为:

def TPR(y_true, y_predict):    tp = TP(y_true, y_predict)    fn = FN(y_true, y_predict)    try:        return tp / (tp + fn)    except:        return 0.0def FPR(y_true, y_predict):    fp = FP(y_true, y_predict)    tn = TN(y_true, y_predict)    try:        return fp / (fp + tn)    except:        return 0.0

对于决策边界的不同,这两个指标的变化趋势是一致的。还是以上面的手写数字识别数据为例,计算不同决策边界下的两指标的值为:

fprs = []tprs = []for threshold in thresholds:    y_predict = np.array(decision_scores >= threshold, dtype='int')    fprs.append(FPR(y_test, y_predict))    tprs.append(TPR(y_test, y_predict))

作出的 TPR 和 FPR 的关系图(即 ROC 曲线)为:

clipboard.png

Scikit Learn 中提供的 roc_curve() 方法传入真实分类结果和 decision_scores,返回 TPR、FPR 和 thresholds:

from sklearn.metrics import roc_curvefprs, tprs, thresholds = roc_curve(y_test, decision_scores)

roc_auc_score() 方法传入真实分类结果和 decision_scores,返回 ROC 曲线表示的面积。

from sklearn.metrics import roc_auc_scoreroc_auc_score(y_test, decision_scores)

面积越大,则模型越好。

源码地址

转载地址:http://qriel.baihongyu.com/

你可能感兴趣的文章
31. Next Permutation
查看>>
Interactive cloth
查看>>
字符编码【转载】
查看>>
mysql中的事物处理
查看>>
Android 车联网天气
查看>>
POJ 2430 状压DP
查看>>
C++Primer第5版学习笔记(三)
查看>>
Centos7系统介绍
查看>>
GIT简单实用
查看>>
Sonar - 部署常见问题及解决方法
查看>>
IOS 学习笔记(3) 视图UITabbarController
查看>>
java基础知识(一)
查看>>
(转)Linux传输大文件(分割传输)
查看>>
1003. 我要通过!(20)
查看>>
phpstudy for linux版环境安装
查看>>
MinGW GCC 7.1.0 2017年6月份出炉啦
查看>>
二叉树的实现(Java语言描述)
查看>>
Json Datable Convert
查看>>
微信小程序制作-随笔4
查看>>
adt 22.6出现的问题
查看>>