上一次我根据knn算法,测试我喜欢的那个她对什么样的男生感兴趣,我还是没有把握我的代码能准确的预测她的心思。冥思苦想之后,我决定测试我的算法,以确定它的有效性。为此,我回忆起老师上课所讲解的性能度量指标,特别是错误率与精度、查准率与查全率,以及ROC曲线。
我开始收集了一批相关数据,并将其划分为训练集和测试集,然后选择合适的K值和距离度量方法。在实验中,我记录下了每次实验的结果,并对算法进行了多次运行和调整。我尝试过不同的K值和距离度量方法,以找到最佳的组合。并计算了其中的错误率与精度、查准率与查全率,以及绘制了ROC曲线。
目录
一、错误率与精度
这两种性能度量适用于二分类任务,也适用于多分类任务。
错误率是分类错误的样本数占样本总数的比例。对样例集D,分类错误率定义为
对于数据分布D和概率密度函数p(·),错误率为
精度则是分类正确的样本数占样本总数的比例。对样例集D,分类精度定义为
对于数据分布D和概率密度函数p(·),精度为
二、查准率和查全率
以西瓜问题为例,若我们关心的是“挑出的西瓜中有多少比例是好瓜”(即准确率),或者“所有好瓜中有多少比例被挑了出来”(即召回率),
查准率亦称“准确率”,查全率亦称“召回率”。
对于二分类问题,可将样例根据其真实类别与学习器预测类别的组合划分为真正例(true positive)、假正例(false positive)、真反例(true negative)、假反例(false negative)四种情形,令TP、FP、TN、FN分别表示其对应的样例数,所以TP+FP+TN+FN=样例总数。
查准率P:
查全率R:
查准率高时,查全率往往偏低;而查全率高时,查准率往往偏低。
若希望将好瓜尽可能多地选出来,则可通过增加选瓜的数量来实现,如果将所有西瓜都选上,那么所有的好瓜也必然都被选上了,但这样查准率就会较低;
若希望选出的瓜中好瓜比例尽可能高,则可只挑选最有把握的瓜,但这样就难免会漏掉不少好瓜,使得查全率较低。
以查准率为纵轴、查全率为横轴作图,就得到了查准率-查全率曲线,简称“P-R曲线”,显示该曲线的图称为“P-R图”。通过以下代码给出示意图
import numpy as np
import matplotlib.pyplot as plt
# 构造样本数据,scores表示预测得分,labels表示真实标签(0或1)
scores = np.array([0.5, 0.8, 0.3, 0.7, 0.6, 0.2])
labels = np.array([1, 1, 0, 1, 0, 0])
# 计算PR曲线上每个点的P值和R值
sorted_indices = np.argsort(-scores) # 按得分从高到低排序
tp_count = 0 # 正确预测的正例数
fp_count = 0 # 错误预测的正例数
p_values = [] # 保存每个点的P值
r_values = [] # 保存每个点的R值
for i in sorted_indices:
if labels[i] == 1: # 预测为正例且真实为正例
tp_count += 1
else: # 预测为正例但真实为负例
fp_count += 1
precision = tp_count / (tp_count + fp_count)
recall = tp_count / np.sum(labels)
p_values.append(precision)
r_values.append(recall)
# 绘制PR曲线
plt.plot(r_values, p_values, marker='o')
plt.xlabel('Recall')
plt.ylabel('Precision')
plt.title('PR Curve')
plt.show()
教材中给出的P-R图(如下图),为方便和美观,图中显示出单调平滑曲线;但现实任务中的P-R曲线常是非单调、不平滑的,在很多局部有上下波动,如上图所示。
三、ROC
ROC全称是“受试者工作特征”(Receiver Operating Characteristic)曲线
与前文介绍的P-R曲线相似,我们根据学习器的预测结果对样例进行排序,按此顺序逐个把样本作为正例进行预测,每次计算出两个重要量的值,分别以它们为横、纵坐标作图,就得到了“ROC曲线”。ROC曲线的纵轴是“真正例率”(True Positive Rate,简称TPR),横轴是“假正例率”(False Positive Rate,简称FPR)。
import numpy as np
import matplotlib.pyplot as plt
# 构造样本数据,scores表示预测得分,labels表示真实标签(0或1)
scores = np.array([0.5, 0.8, 0.3, 0.7, 0.6, 0.2])
labels = np.array([1, 1, 0, 1, 0, 0])
# 计算ROC曲线上每个点的FPR值和TPR值
sorted_indices = np.argsort(-scores) # 按得分从高到低排序
tp_count = 0 # 正确预测的正例数
fp_count = 0 # 错误预测的正例数
fpr_values = [] # 保存每个点的FPR值
tpr_values = [] # 保存每个点的TPR值
for i in sorted_indices:
if labels[i] == 1: # 预测为正例且真实为正例
tp_count += 1
else: # 预测为正例但真实为负例
fp_count += 1
fpr = fp_count / np.sum(1-labels)
tpr = tp_count / np.sum(labels)
fpr_values.append(fpr)
tpr_values.append(tpr)
# 绘制ROC曲线
plt.plot(fpr_values, tpr_values, marker='o')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('ROC Curve')
plt.show()
现实任务中通常是利用有限个测试样例来绘制ROC图,此时仅能获得有限个(真正例率,假正例率)坐标对,无法产生下图中的光滑ROC曲线,只能绘制出如上图所示的近似ROC曲线
四、小结
性能度量是评价机器学习算法性能好坏的重要指标,其中错误率、精度、查准率和查全率、ROC曲线是常见的性能度量方式。
- 错误率是分类错误的样本数占总样本数的比例;错误率越小,模型性能越好。
- 精度是分类正确的样本数占总样本数的比例;精度越高,模型性能越好。
- 查准率是所有被预测为正例的样本中,真正是正例的样本所占的比例;查准率越高,模型对于预测为正例的结果越可信。
- 查全率是所有真实正例中,被正确预测为正例的样本所占的比例;查全率越高,模型对于真实为正例的情况预测的准确程度越高。
- ROC曲线展示的是不同阈值下的TPR和FPR之间的关系;ROC曲线越靠近左上角,说明模型性能越好,当ROC曲线沿着左上角移动时,既能保证查准率越来越高,也能保证查全率越来越高。
总结一下,在使用机器学习算法进行分类任务时,我们需要综合考虑以上多种性能度量方式,以全面评价算法的性能表现和优劣。同时,在分析结果时,需要综合考虑各种度量方式的优缺点,选择最适合的性能度量方式,以充分发挥机器学习算法的性能。