数据挖掘学习--精准率和召回率

1.前言

机器学习中,我们的任务通俗的来讲就是训练出更好更准确更优的模型。那么面对不同的模型,我们应该用什么样的指标来评判他的优劣呢?最简单的一个指标,就是模型准确率,通过预测值和真实值的比值直接判断模型是否准确。当然很明显这是有缺陷的。
这里就有好几个更加有意义的模型评估标准:精准率,召回率,TPR,FPR,f1-score以及ROC和AUC值等。本文先介绍一下精准率和召回率。

2.精准率和召回率出现解决的问题

本文介绍的指标都是对最简单的二分类问题来分析。精准率(precision)和召回率(recall)两个都是衡量模型的指标。那有人会问为什么会想着诞生这两个指标,而不用通用的更好理解的模型准确率来衡量呢?这个就是因为,我们的数据样本并非那么优秀,那么理想。理想数据样本下,每一个类别中样本数量都相近,但是,我们在实际的情况下,往往遇到的数据样本并非有这种特性,他们有的就会是某一类别的样本量特别多,占了所有样本的大部分;反而剩下的另一类别的样本数量十分少。若此时仍然用模型准确率(accuracy),就会出现问题。

举个例子:对于一个模型,假如现在我们有10000个数据样本,其中预测的样本有9980个是健康的,20个是患癌症的。而实际上我们这些样本中共有9990个是健康的,10个是患病的。不难看出这个模型准确率是相当高的,达到了99.9%。但是,这个值真的有意义吗?或者说我们的这个值真的能够反映我们的模型是这么准确的一个模型吗?

其实我们也很容易察觉端倪。问题就出现在了这个样本的分布是极端的,我们可以称之为是极度偏斜数据(Shewed Data),这样的情况我们仅仅用的是模型准确度来衡量,就会使得造成一种情况,只要预测到大部分人健康就好了,那么模型准确度就会由于偏斜数据的影响,会变高。说白了就是某个对我们实验而言不重要的类别样本数量占比过大,导致我们关注的类别的预测成功与否对模型准确度影响太小,而我们关注的就是这么一个样本少的类别。

出现了这种问题,当然就有新的指标出现。我们能不能换个角度想,我们找一个指标,是表明在某个类别下,我们预测正确的概率?而本文的精准度(precision)和召回率(recall)就是这样诞生了。

3.精准率和召回率

首先,我们要把预测样本分为4个类别:
a.TP:预测为正类,预测正确的样本数量
b.FP:预测为正类,预测错误的样本数量
c.TN:预测为负类,预测正确的样本数量
d.FN:预测为负类,预测错误的样本数量

按照这4中分类,我们可以得到这么一个混淆矩阵(confusion_matrix)
数据挖掘学习--精准率和召回率_第1张图片
这里给出精准率和召回率的公式:
数据挖掘学习--精准率和召回率_第2张图片
数据挖掘学习--精准率和召回率_第3张图片
解释一下两者代表的含义:

精准率:我们做了100个预测值为1的数据样本中,其中有多少个是预测正确的(也就是他的真实值也是1)的样本数量。(也就是说模型预测了那么多,究竟有多少是预测正确的?)

召回率:我们对100个真实值为1的数据样本进行预测,其中有多少个是预测正确的(也就是预测值也为1)的样本数量。(也就是说模型对这么多正类的样本,究竟有多少是预测正确的?)

再来解释一下为什么要精准率和召回率。精准率和召回率体现的是模型在我们想要关注的类别样本里面去分析(就类比患癌的样本),这是我们实验关心的;相比之下我们可以忽略掉那些不重要的样本的预测结果和预测准确率(类比健康的样本)。这就是这两个指标和模型准确率的不同之处。
再提一点,我们会将我们关注的类作为是正类,不关注的类作为负类,这直接影响我们的TP、FP等值,精准率和召回率也会相应的不一样。

4.自己编写的实现代码:

#真正值
def TP(y , y_predict):
    assert len(y) == len(y_predict) , "The length of y is not equal to y_predict."
    return np.sum(((y_predict == 1) & (y == 1)))

#假正值
def FP(y , y_predict):
    assert len(y) == len(y_predict), "The length of y is not equal to y_predict."
    return np.sum(((y_predict == 1)&( y == 0)))

#真负值
def TN(y , y_predict):
    assert len(y) == len(y_predict), "The length of y is not equal to y_predict."
    return np.sum(((y_predict == 0) & (y == 0)))

#假负值
def FN(y , y_predict):
    assert len(y) == len(y_predict), "The length of y is not equal to y_predict."
    return np.sum(((y_predict == 0) & (y == 1)))

#混淆矩阵
def confusion_matrix(y , y_predict):
    assert len(y) == len(y_predict), "The length of y is not equal to y_predict."
    return np.array(
        [
            [TN(y , y_predict) , FP(y , y_predict)],
            [FN(y , y_predict) , TP(y , y_predict)]
        ]
    )

#precision精确度
def precision(y , y_predict):
    assert len(y) == len(y_predict), "The length of y is not equal to y_predict."
    try:
        return TP(y, y_predict) / (TP(y, y_predict) + FP(y, y_predict))
    except:
        return 0.0

#recall召回率
def recall(y , y_predict):
    assert len(y) == len(y_predict), "The length of y is not equal to y_predict."
    try:
        return TP(y , y_predict) / (TP(y , y_predict) + FN(y , y_predict))
    except:
        return 0.0

5.再sklearn库中的实现

from sklearn.metrics import precision_score
from sklearn.metrics import recall_score
#默认average值是'binary',意思就是二分类问题,只有两个类
precision = precision_score(y_test , y_predict )
recall = recall_score(y_test , y_predict)

6.关于精准率和召回率的补充
对于模型来说,精准率和召回率的变化是成反比的。
而精准率和召回率都是越大越好。

你可能感兴趣的:(数据挖掘学习--精准率和召回率)