性能度量——Confusion Matrix混淆矩阵

Confusion Matrix

当数据是极度偏斜的数据集(例如某些罕见疾病)的时候,单纯用分类准确率来评判算法的话就很没用(因为即使你说百分百都是健康的人准确率可能也有百分九十九),可以通过建立混淆矩阵进行分析。
性能度量——Confusion Matrix混淆矩阵

Precision and Recall

在这里有两个名词Precision精准率Recall召回率
精准率就是我们所关注的那一类事物的预测效果(How many selected items are relevant?),可以理解为做了一百次分类为阳性的预测有多少次是成功的,如前面所说的罕见疾病,精准率在这里就是预测疾病的成功率;
而召回率就是当关注事件真正发生的时候预测到它的效果(How many relevant items are selected?),可以理解为对分类为阳性的样本做预测有多少次是成功的,比如对于所有罕见疾病患者诊断出他真的有病的概率(周志华把它翻译成查准率和查全率让我很懵),计算方法如下:
性能度量——Confusion Matrix混淆矩阵性能度量——Confusion Matrix混淆矩阵
用这两个作为指标会比之前简单用预测成功数/预测数得到的准确率更加具体。
举例:如果预测所有人都没罕见疾病而实际上有5个人,即预测全部都是Negative,此时准确率99.95%,
但TP=0,FP=0,TN=9995,FN=5
Precision = 0 / ( 0 + 0 )= 0
Recall = 0 / ( 0 + 5 ) = 0

F1

虽说有些像股票更在意精准率而诊病更看重召回率,这二者有某种程度上互相牵制,但是有时也需要兼顾二者,就能通过用F1score了,F1实际上是精准率和召回率的调和平均值。
性能度量——Confusion Matrix混淆矩阵
变变形:性能度量——Confusion Matrix混淆矩阵
不过也有可能他们二者都有不同的相对重要性,那么可以加上权重:
性能度量——Confusion Matrix混淆矩阵
β>1时对召回率更大影响,β<1时对准确率更大影响。

ROC

又出现了两个定义False Positive Rate和True Positive Rate,分别代表在阴性样本中判成阳性的概率和在阳性样本中判出是阳性样本的概率,这二者也是有某种程度上是有正比关系的。
性能度量——Confusion Matrix混淆矩阵
通过绘制出以FPR为横轴,TPR纵轴,通过设定阈值为划出的曲线来评估算法优劣,一般是以它曲线下的面积AUC为指标。
性能度量——Confusion Matrix混淆矩阵

可能是实现(仅仅实现了二分类)

打了个混淆矩阵的代码:

import numpy as np


class confusionMatrix:

    def __init__(self, y_true, y_predict):
        assert len(y_true) == len(y_predict)
        self.tn = np.sum((y_true == 0) & (y_predict == 0))
        self.fn = np.sum((y_true == 1) & (y_predict == 0))
        self.fp = np.sum((y_true == 0) & (y_predict == 1))
        self.tp = np.sum((y_true == 1) & (y_predict == 1))

    def confusion_matrix(self):
        return np.array([
            [self.tn, self.fp],
            [self.fn, self.tp]
        ])

    def precision_score(self):
        tp = self.tp
        fp = self.fp
        try:
            return tp / (tp + fp)
        except:
            return 0.0

    def recall_score(self):
        tp = self.tp
        fn = self.fn
        try:
            return tp / (tp + fn)
        except:
            return 0.0
        
        
    def tpr(self):
        tp = self.tp
        fn = self.fn
        try:
            return tp / (tp + fn)
        except:
            return 0.


    def fpr(self):
        fp = self.fp
        tn = self.tn
        try:
            return fp / (fp + tn)
        except:
            return 0.

    def f1_score(self):
        p = self.precision_score()
        r = self.recall_score()
        try:
            return 2 * p * r / (p + r)
        except:
            return 0.0

    def f1_beta_score(self, beta):
        p = self.precision_score()
        r = self.recall_score()
        try:
            return (1 + beta) ** 2 * p * r / (beta ** 2 * p + r)
        except:
            return 0.0

然后可以用这个画出来…(decision_scores即最后得到的分数,如回归问题会通过分数来进行分类大于0为1小于0为0,那这里就是设阈值在最小值到最大值之间然后大于阈值为1小于阈值为0来绘图)

fprs = []
tprs = []
thresholds = np.arange(np.min(decision_scores), np.max(decision_scores), 0.1)
for t in thresholds:
    y_predict = np.array(decision_scores >= t, dtype='int')
    matrix = confusionMatrix(y_test, y_predict)
    fprs.append(matrix.tpr())
    tprs.append(matrix.fpr())
plt.plot(fprs, tprs)
plt.show()