在机器学习中,正确评估分类模型的性能至关重要。本课程将深入介绍各种评估指标和技术,帮助您更好地理解和评估模型的效果。
1. 准确率
对分类模型的性能评估时经常使用准确率(Accuracy)评估方法,准确率是指分类模型正确预测的样本数量与总样本数量之比。
例如:
假设:样本中有 6 个恶性肿瘤样本,4 个良性肿瘤样本。
模型 A:预测对了 5 个恶性肿瘤样本,4 个良性肿瘤样本,其准确率为:90%
模型 B:预测对了 6 个恶性肿瘤样本,3 个良性肿瘤样本,其准确率为:90%
from sklearn.metrics import accuracy_score import pandas as pd if __name__ == '__main__': # 样本集中共有6个恶性肿瘤样本, 4个良性肿瘤样本 y_true = ['恶性', '恶性', '恶性', '恶性', '恶性', '恶性', '良性', '良性', '良性', '良性'] # 1. 模型 A: 预测对了 5 个恶性肿瘤样本, 4个良性肿瘤样本 y_pred = ['恶性', '恶性', '恶性', '恶性', '恶性', '良性', '良性', '良性', '良性', '良性'] acc = accuracy_score(y_true, y_pred) print('acc:', acc) # 2. 模型 B: 预测对了 6 个恶性肿瘤样本, 3 个良性肿瘤样本 y_pred = ['恶性', '恶性', '恶性', '恶性', '恶性', '恶性', '恶性', '良性', '良性', '良性'] acc = accuracy_score(y_true, y_pred) print('acc:', acc)
acc: 0.9 acc: 0.9
2. 混淆矩阵
准确率是一个较为粗粒度的分类评估方法,它并不能进行更加细粒度的评估场景。例如:在一个肿瘤预测的二分类问题中,我们更加看重模型对恶性肿瘤的预测能力,而不仅仅是准确率。模型 B 把所有潜在的恶性肿瘤患者全部预测出来,模型 A 只能把 5/6 的恶性肿瘤患者预测出来,哪一个模型对于当前问题场景更好呢?显然是前者。
所以,所以,我们需要引入其他的模型评估方法。
想要获得更加精细的分类评估方法,得将预测结果进行更为精细的划分,这就是混淆矩阵(Confusion Matrix)。
正例(预测结果) | 负例(预测结果) | |
正例(真实结果) | 真正例(TP) | 假负例(FN) |
负例(真实结果) | 假正例(FP) | 真负例(TN) |
混淆矩阵作用就是统计下在测试集中:
- 真实值是 正例 的样本中,被预测为 正例 的样本数量有多少,这部分样本叫做 真正例(TP,True Positive)
- 真实值是 正例 的样本中,被预测为 负例 的样本数量有多少,这部分样本叫做 假负例(FN,False Negative)
- 真实值是 负例 的样本中,被预测为 正例 的样本数量有多少,这部分样本叫做 假正例(FP,False Positive)
- 真实值是 负例 的样本中,被预测为 负例 的样本数量有多少,这部分样本叫做 真负例(TN,True Negative)
True Positive :整体表示样本真实的类别
Positive :第二个词表示样本被预测为的类别
例子:
样本集中有 6 个恶性肿瘤样本,4 个良性肿瘤样本,我们假设恶性肿瘤为正例,则:
- 模型 A:预测对了 3 个恶性肿瘤样本,4 个良性肿瘤样本
- 真正例 TP 为:3
- 假负例 FN 为:3
- 假正例 FP 为:0
- 真负例 TN:4
- 模型 B:预测对了 6 个恶性肿瘤样本,1个良性肿瘤样本
- 真正例 TP 为:6
- 假负例 FN 为:0
- 假正例 FP 为:3
- 真负例 TN:1
我们会发现:TP+FN+FP+TN = 总样本数量
通过上面四种情况,将预测后的结果划分为 4 部分,分别是:TP、FN、TN、FP。我们通过上述 4 种信息,构成了分类问题中的重要评估指标。
from sklearn.metrics import confusion_matrix import pandas as pd if __name__ == '__main__': # 样本集中共有6个恶性肿瘤样本, 4个良性肿瘤样本 y_true = ['恶性', '恶性', '恶性', '恶性', '恶性', '恶性', '良性', '良性', '良性', '良性'] labels = ['恶性', '良性'] # 1. 模型 A: 预测对了3个恶性肿瘤样本, 4个良性肿瘤样本 y_pred = ['恶性', '恶性', '恶性', '良性', '良性', '良性', '良性', '良性', '良性', '良性'] matrix = confusion_matrix(y_true, y_pred, labels=labels) print(pd.DataFrame(matrix, columns=labels, index=labels)) # 2. 模型 B: 预测对了6个恶性肿瘤样本, 1个良性肿瘤样本 y_pred = ['恶性', '恶性', '恶性', '恶性', '恶性', '恶性', '恶性', '恶性', '恶性', '良性'] matrix = confusion_matrix(y_true, y_pred, labels=labels) print(pd.DataFrame(matrix, columns=labels, index=labels))
恶性 良性 恶性 3 3 良性 0 4 恶性 良性 恶性 6 0 良性 3 1
3. 精确率(精度、查准率)
精确率(Precision)是指被分类器正确分类的正样本(True Positive)数目与所有被分类为正样本的样本数目的比率。
比如,我们把恶性肿瘤当做正例样本,我们希望知道在模型预测出的所有的恶性肿瘤样本中,真正的恶性肿瘤样本占比。即:模型对恶性肿瘤的预测精确率有多少?
如果预测出 10 个恶性肿瘤样本,并且这 10 个也是真正的恶性肿瘤,那么精度就是 100%。如果 10 个中,只有 3 个是真正的恶性肿瘤,那么精度就是 30%.
也就是说,我们关心模型预测的准不准,并不关心预测的全不全。
例子:
样本集中有 6 个恶性肿瘤样本,4 个良性肿瘤样本,我们假设恶性肿瘤为正例,则:
- 模型 A:预测对了 3 个恶性肿瘤样本,4 个良性肿瘤样本
- 真正例 TP 为:3
- 假负例 FN 为:3
- 假正例 FP 为:0
- 真负例 TN:4
- 精确率:3/(3+0) = 100%
- 模型 B:预测对了 6 个恶性肿瘤样本,1个良性肿瘤样本
- 真正例 TP 为:6
- 假负例 FN 为:0
- 假正例 FP 为:3
- 真负例 TN:1
- 精确率:6/(6+3) = 67%
from sklearn.metrics import precision_score if __name__ == '__main__': # 样本集中共有6个恶性肿瘤样本, 4个良性肿瘤样本 y_true = ['恶性', '恶性', '恶性', '恶性', '恶性', '恶性', '良性', '良性', '良性', '良性'] # 1. 模型 A: 预测对了3个恶性肿瘤样本, 4个良性肿瘤样本 y_pred = ['恶性', '恶性', '恶性', '良性', '良性', '良性', '良性', '良性', '良性', '良性'] # pos_label 指定那个类别是正例 result = precision_score(y_true, y_pred, pos_label='恶性') print('模型A精确率:', result) # 2. 模型 B: 预测对了6个恶性肿瘤样本, 1个良性肿瘤样本 y_pred = ['恶性', '恶性', '恶性', '恶性', '恶性', '恶性', '恶性', '恶性', '恶性', '良性'] result = precision_score(y_true, y_pred, pos_label='恶性') print('模型B精确率:', result)
输出结果:
模型A精确率: 1.0 模型B精确率: 0.67
4. 召回率(查全率)
召回率也叫做查全率,指的是预测为真正例样本占所有真实正例样本的比重。例如:我们把恶性肿瘤当做正例样本,则我们想知道模型是否能把所有的恶性肿瘤患者都预测出来。
例子:
样本集中有 6 个恶性肿瘤样本,4 个良性肿瘤样本,我们假设恶性肿瘤为正例,则:
- 模型 A:预测对了 3 个恶性肿瘤样本,4 个良性肿瘤样本
- 真正例 TP 为:3
- 假负例 FN 为:3
- 假正例 FP 为:0
- 真负例 TN:4
- 精确率:3/(3+0) = 100%
- 召回率:3/(3+3)=50%
- 模型 B:预测对了 6 个恶性肿瘤样本,1个良性肿瘤样本
- 真正例 TP 为:6
- 假负例FN 为:0
- 假正例 FP 为:3
- 真负例 TN:1
- 精确率:6/(6+3) = 67%
- 召回率:6/(6+0)= 100%
from sklearn.metrics import recall_score if __name__ == '__main__': # 样本集中共有6个恶性肿瘤样本, 4个良性肿瘤样本 y_true = ['恶性', '恶性', '恶性', '恶性', '恶性','恶性', '良性', '良性', '良性', '良性'] # 1. 模型 A: 预测对了3个恶性肿瘤样本, 4个良性肿瘤样本 y_pred = ['恶性', '恶性', '恶性', '良性', '良性', '良性', '良性', '良性', '良性', '良性'] result = recall_score(y_true, y_pred, pos_label='恶性') print('模型A召回率:', result) # 2. 模型 B: 预测对了6个恶性肿瘤样本, 1个良性肿瘤样本 y_pred = ['恶性', '恶性', '恶性', '恶性', '恶性', '恶性', '恶性', '恶性', '恶性', '良性'] result = recall_score(y_true, y_pred, pos_label='恶性') print('模型B召回率:', result)
输出结果:
模型A召回率: 0.5 模型B召回率: 1.0
5. F1-score(综合精度和召回率)
F1-score 是一种常用的性能度量指标,它综合考虑了模型的精确度和召回率,是这两者的调和平均数,其计算公式如下:
调和平均数对数据集中的较小数值更敏感。如果数据集中有极小的值,它会显著降低调和平均数的值。
from scipy.stats import hmean print(hmean([0.0, 1.0])) print(hmean([1.0, 0.0])) print(hmean([0.0, 0.0])) print(hmean([1.0, 1.0]))
0.0 0.0 0.0 1.0
所以,当精度和召回率都高的时候,f1-score 才会高。
样本集中有 6 个恶性肿瘤样本,4 个良性肿瘤样本,我们假设恶性肿瘤为正例,则:
- 模型 A:预测对了 3 个恶性肿瘤样本,4 个良性肿瘤样本
- 真正例 TP 为:3
- 假负例 FN 为:3
- 假正例 FP 为:0
- 真负例 TN:4
- 精确率:3/(3+0) = 100%
- 召回率:3/(3+3)=50%
- F1-score:(2*3)/(2*3+3+0)=67%
- 模型 B:预测对了 6 个恶性肿瘤样本,1个良性肿瘤样本
- 真正例 TP 为:6
- 假负例 FN 为:0
- 假正例 FP 为:3
- 真负例 TN:1
- 精确率:6/(6+3) = 67%
- 召回率:6/(6+0)= 100%
- F1-score:(2*6)/(2*6+0+3)=80%
from sklearn.metrics import f1_score if __name__ == '__main__': # 样本集中共有6个恶性肿瘤样本, 4个良性肿瘤样本 y_true = ['恶性', '恶性', '恶性', '恶性', '恶性','恶性', '良性', '良性', '良性', '良性'] # 1. 模型 A: 预测对了3个恶性肿瘤样本, 4个良性肿瘤样本 y_pred = ['恶性', '恶性', '恶性', '良性', '良性', '良性', '良性', '良性', '良性', '良性'] result = f1_score(y_true, y_pred, pos_label='恶性') print('模型A f1-score:', result) # 2. 模型 B: 预测对了6个恶性肿瘤样本, 1个良性肿瘤样本 y_pred = ['恶性', '恶性', '恶性', '恶性', '恶性', '恶性', '恶性', '恶性', '恶性', '良性'] result = f1_score(y_true, y_pred, pos_label='恶性') print('模型B f1-score:', result)
输出结果:
模型A f1-score: 0.67 模型B f1-score: 0.8