1.错误率、误差与过拟合
1.1错误率与误差
错误率:分类错误的样本数占样本总数的比例。
误差:学习器的实际预测输出与样本的真实输出之间的差异称为“误差”,学习器在训练集上的误差称为“训练误差”或“经验误差”,在新样本上的误差称为“泛化误差”。
1.2欠拟合与过拟合
过拟合:学习器把训练样本学的“太好”,将训练样本自身的一些特点当作了所有潜在样本都会具有的一般性质,导致泛化性能能下降。解决方法:提前停止训练等
欠拟合:学习器对训练样本的一般属性尚未学好。解决方法:在决策树学习中拓展分支、在神经网络学习中增加训练轮数等。
2.评估方法
2.1留出法
"留出法"直接将数据集D划分为两个互斥的集合,其中一个集合作为训练集S,另一个作为测试集T,即D=S∪T,S∩T=∅。在S上训练出模型后,用T来评估其测试误差,作为对泛化误差的估计。
2.2交叉验证法:
“交叉验证法”先将数据集D划分为k个大小相似的互子集,即。每个子集Di都尽可能保持数据分布的一致性,即从D中通过分层采样的到。然后,每次用k-1个子集的并集作为训练集,余下的那个子集作为测试集;这样就可获得k组训练/测试集,从而可进行k次训练和测试,最终返回的是这k个测试结果的均值。
2.3验证集
在模型训练完成时,我们通常采用测试集来测试模型的训练程度,从而进行调整,但是进行调整之后,由于测试集的数据已经用于测试模型,模型已经“认识”这些数据了,测试集的数据不能再用作测试数据,这时我们可以引入一个验证集,用来专门测试模型并进行模型的调整。相当于训练集是平时作业,用于锻炼学生的做题能力,而验证集是模拟考试,用于验证学生的学习程度并进行调整,而测试集是正式考试,用于查看模型最终的训练结果。
3.性能度量
3.1混淆矩阵
混淆矩阵也称误差矩阵,是表示精度评价的一种标准格式,用n行n列的矩阵形式来表示
真正例(TP):把正例预测为正例
假正例(FP):把假例预测为正例
假反例(FN):把正例预测为反例
真反例(TN):把反例预测为反例
3.2查准率与查全率
查准率:预测出来为正例中真正的正例所占的比例。公式表示如下
查全率:预测出来正确的正类占所有真实正类的比例。公式表示如下
3.3P-R曲线
召回率,纵轴精确率。分类器在不同阈值下会得到一系列不同的精确率和召回率值,通过将这些值以召回率为横坐标、精确率为纵坐标绘制成曲线,即为PR曲线。曲线上每个点表示了在对应召回率下的最大精确率值。当P=R时成为平衡点,如果这个值较大,则说明学习器的性能较好。所以PR曲线越靠近右上角性能越好。
查准率和查全率是一对矛盾的变量。一般来说,查准率高时,查全率往往偏低;而查全率高时,查准率往往偏低。通常只有在一些简单任务中,才可能使查准率和查全率都很高。
3.4ROC曲线与AUC
ROC曲线:ROC全称Receiver Operating Characteristic,即受试者工作特征,坐标图式的分析工具。ROC曲线的纵轴是"真正例率" (True Positive Rate,简称 TPR),横轴是"假正例率" (False PositiveRate, FPR)。下图为TPR与FPR的计算
AUC:ROC曲线下方的面积(AUC)可以用来作为评估模型模型性能的指标。如当两个模型的ROC曲线发生交叉,则很难说哪一个模型更好,这时候可以用AUC来作为一个比较合理的判据。ROC曲线一般都处于y=x这条直线的上方,所以取值范围在0.5和1之间,使用AUC作为评价指标是因为ROC曲线在很多时候并不能清晰地说明哪个分类器的效果更好,而AUC作为一个数值,其值越大代表分类器效果更好,即ROC图像越靠坐上角分类器效果越好。
4.利用PR曲线与ROC曲线评估KNN模型
利用PR曲线与ROC曲线来评估k-近邻算法
def evaluate_model():
hoRatio = 0.10 # 90%的数据用于训练,10%的数据用于测试
datingDataMat, datingLabels = file2matrix('datingTestSet.txt')
normMat, ranges, minVals = autoNorm(datingDataMat)
m = normMat.shape[0]
numTestVecs = int(m * hoRatio) # 用于测试的行数
# 准备存储结果
y_true = []
y_scores = defaultdict(list)
for i in range(numTestVecs):
true_label = datingLabels[i]
y_true.append(true_label)
# 对每个测试样本,计算它与所有训练样本的距离
distances = np.sqrt(np.sum((normMat[numTestVecs:m,:] - normMat[i,:])**2, axis=1))
# 对每个类别计算得分(使用距离的倒数作为相似度度量)
class_scores = defaultdict(float)
for j in range(len(distances)):
train_label = datingLabels[numTestVecs + j]
similarity = 1.0 / (distances[j] + 1e-6) # 加一个小数避免除以零
class_scores[train_label] += similarity
# 存储每个类别的得分
for class_label in [1, 2, 3]:
y_scores[class_label].append(class_scores.get(class_label, 0.0))
# 将标签和分数转换为适合scikit-learn的格式
y_true = np.array(y_true)
y_scores = {k: np.array(v) for k, v in y_scores.items()}
# 绘制每个类别的ROC曲线和PR曲线
plt.figure(figsize=(12, 10))
# ROC曲线
plt.subplot(2, 2, 1)
for class_label in [1, 2, 3]:
y_true_binary = (y_true == class_label).astype(int)
fpr, tpr, _ = roc_curve(y_true_binary, y_scores[class_label])
roc_auc = auc(fpr, tpr)
plt.plot(fpr, tpr, label=f'Class {class_label} (AUC = {roc_auc:.2f})')
plt.plot([0, 1], [0, 1], 'k--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('ROC Curve for Each Class')
plt.legend(loc="lower right")
# PR曲线
plt.subplot(2, 2, 2)
for class_label in [1, 2, 3]:
y_true_binary = (y_true == class_label).astype(int)
precision, recall, _ = precision_recall_curve(y_true_binary, y_scores[class_label])
avg_precision = average_precision_score(y_true_binary, y_scores[class_label])
plt.plot(recall, precision, label=f'Class {class_label} (AP = {avg_precision:.2f})')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('Recall')
plt.ylabel('Precision')
plt.title('Precision-Recall Curve for Each Class')
plt.legend(loc="lower left")
plt.tight_layout()
plt.show()
结果截图:
5.实验总结
本次实验的内容旨在掌握如何衡量一个模型的好坏,学习了错误率、误差、混淆矩阵、TPR、FPR等概念,明白了如何使用画出混淆矩阵并且得出一个模型的TPR、FPR与查准率、查全率,并且了解了PR曲线与ROC曲线的作用,PR曲线与ROC曲线是衡量一个模型好坏的重要指标,能够直观地显示出一个模型的性能,此次的学习内容同时也让我对机器学习的相关概念有了更深一步的了解,为接下来的学习做好了铺垫。