本文章将要探讨的是机器学习里分类问题中常用的准确率、精确率和召回率这三种评估指标。
首先,给出我们下面要用到的样例。
l1 = [0, 1, 1, 1, 0, 0, 0, 1] # 真实数据
l2 = [0, 1, 0, 1, 0, 1, 0, 0] # 预测结果
为了方便我们后续的学习和计算,这儿以一个二分类问题为例,即样本标签只有 和 两种,约定 列表是我们真实的标签数据, 列表则是我们模型预测的结果。
在讨论这三个指标前,我们需要了解一些术语。
1 前置芝士
1.1 真阳性(TP)
给定一张图片,如果我们的模型预测该图片里有气球,而该图片里实际上就是有气球的,则视为真阳性。
用 Python 实现如下。
def true_positive(y_true, y_pred):
tp = 0
for yt, yp in zip(y_true, y_pred):
# 若真实标签为正且预测标签也为正,计数器加一
if yt == 1 and yp == 1:
tp += 1
return tp
接下来,检查一下我们编写的代码是否正确。
In [X]: true_positive(l1, l2)
Out[X]: 2
与手动计算的结果一样,第二个和第四个样本的真实标签和模型预测标签一致,都为 。
1.2 真阴性(TN)
给定一张图片,如果我们的模型预测该图片里没有气球,而该图片里实际上就没有气球,则视为真阴性。
def true_negative(y_true, y_pred):
tn = 0
for yt, yp in zip(y_true, y_pred):
# 若真实标签为负且预测标签也为负,计数器加一
if yt == 0 and yp == 0:
tn += 1
return tn
In [X]: true_negative(l1, l2)
Out[X]: 3
这与手动计算的结果一样,第一个、第五个和第七个样本的真实标签和模型预测标签一致,都为 。
1.3 假阳性(FP)
给定一张图片,如果我们的模型预测该图片里有气球,而该图片里实际上就没有气球,则视为假阳性。
def false_positive(y_true, y_pred):
fp = 0
for yt, yp in zip(y_true, y_pred):
# 若真实标签为负而预测标签为正,计数器加一
if yt == 0 and yp == 1:
fp += 1
return fp
In [X]: false_positive(l1, l2)
Out[X]: 1
这与手动计算的结果一样,第六个样本的真实标签为 但模型预测标签为 。
1.4 假阴性(FN)
给定一张图片,如果我们的模型预测该图片里没有气球,而该图片里实际上就是有气球的,则视为假阴性。
def false_negative(y_true, y_pred):
fn = 0
for yt, yp in zip(y_true, y_pred):
# 若真实标签为正而预测标签为负,计数器加一
if yt == 1 and yp == 0:
fn += 1
return fn
In [X]: false_negative(l1, l2)
Out[X]: 2
这也与手动计算的结果一样,第三个和最后一个样本的真实标签都为 但模型预测标签为 。
2. 准确率(Accuracy)
准确率是机器学习中常用的评估指标之一,用于衡量模型预测结果的准确性。准确率通常定义为模型正确预测的样本数量与总样本数量的比值。我们还可以用 节~ 节提到的术语来表示它。
知道了公式,那么它的实现便很简单了。
def accuracy(y_true, y_pred):
tp = true_positive(y_true, y_pred)
fp = false_positive(y_true, y_pred)
fn = false_negative(y_true, y_pred)
tn = true_negative(y_true, y_pred)
# 计算准确率
accuracy_score = (tp + tn) / (tp + tn + fp + fn)
return accuracy_score
In [X]: accuracy(l1, l2)
Out[X]: 0.625
由此可知,我们模型的准确率为 ,即我们的模型只准确预测了 个样本的标签。
3. 精确率(Precision)
精确率,也叫查准率,它也是机器学习中一个常用来衡量模型预测结果的准确性的工具。精确率的定义是:在所有被模型预测为正例的样本中,真正的正例所占的比例。用我们的术语来表示是这样。
同样,我们也可以用 Python 将它实现。
def precision(y_true, y_pred):
tp = true_positive(y_true, y_pred)
fp = false_positive(y_true, y_pred)
# 计算精确率
precision = tp / (tp + fp)
return precision
In [X]: precision(l1, l2)
Out[X]: 0.6666666666666666
观察我们的 列表,预测的标签为 的样本有 个,但真阳性的样本只有 个,所以精确率为 ,这与我们的程序运行结果一致。
4. 召回率(Recall)
召回率通常和精确率一起用于衡量模型的性能。召回率的定义是:在所有实际为正例的样本中,被模型正确预测为正例的样本所占的比例,即模型能够找到多少真正的正例。用我们的术语表示如下。
def recall(y_true, y_pred):
tp = true_positive(y_true, y_pred)
fn = false_negative(y_true, y_pred)
# 计算召回率
recall = tp / (tp + fn)
return recall
写完代码,我们来测试一下。
In [X]: recall(l1, l2)
Out[X]: 0.5
根据程序输出结果,我们模型的召回率为 ,是否正确呢? 列表里标签为 的样本有 个,但这 个样本被模型正确地预测标签为 的只有其中 个,即第二个和第四个样本,所以答案正确!
5. 意义
现在我们已经了解了这三个评估指标的定义和计算方式,它们都很重要,但现实中很少有十全十美的模型。接下来我们来思考一个问题,在什么样的情形下,我们的模型需要更侧重于哪个指标呢?
5.1 准确率更重要
一般来讲,当数据集相对平衡,正例和负例的数量相当,且错误预测的代价很高时,准确率可能更重要。因为这能帮助我们从全局的角度来判断一个模型或者一个系统的能力是否足够强。此外,准确率作为一个总体的评估指标,在一些简单的分类问题中,可以用于比较不同模型或方法的性能,从而帮助人们的选择。
5.2 精确率更重要
当正例的预测非常关键,且我们更关注模型在预测正例时的准确性时,精确率可能更重要。例如,在立即邮件拦截中,我们肯定是更希望模型能够识别出真正的垃圾邮件,而不是误判普通的电子邮件为垃圾邮件,从而影响人们的正常交流。
5.3 召回率更重要
当正例非常重要,且我们希望尽可能多地找到所有正例时,召回率可能更重要。通俗地讲,就是宁可错杀一千,也不放过一个。例如,在地震预测系统中,我们一般都要求模型能够预测出所有可能发生地震的地理位置信息,尽管可能会有预测错误的时候,即某一地点实际上根本就没发生地震,但是如果系统漏报一个会发生地震的地点时,则会酿成难以计数的后果。
然而,在实际应用中,通常需要综合考虑准确率、精确率和召回率,以及具体问题的需求和权衡,这就是需要我们在实践中不断地学习了。