目录
一、经验误差与过拟合
1.1错误率、误差
错误率(error rate):分类错误的样本数占总样本数的比例,即在m个样本中有a个样本分类错误,则错误率E=a/m;相应的,1-a/m称为"精度",即“精度=1-错误率”。
一般,我们把学习器的实际预测输出与样本的真实输出之间的差异称为“误差”,学习器在训练集上的误差称为“训练误差”或“经验误差”,在新样本上的误差称为“泛化误差”。
1.2欠拟合与过拟合
欠拟合:指学习器对训练样本的一般性质尚未学好,克服欠拟合的方法有:在决策树学习中拓展分支、在神经网络学习中增加训练轮数等。
过拟合:学习器把训练样本学的“太好”,将训练样本自身的一些特点当作了所有潜在样本都会具有的一般性质,导致泛化性能能下降。过拟合无法彻底避免。
二、评估方法
通常,我们可通过实验测试来对学习器的泛化误差进行评估并进而作出选择。为此,需使用一个“测试集”来测试学习器对新样本的判别能力,然后以测试集上的“测试误差”作为泛化误差的近似。通常我们假设测试样本也是从样本真实分布中独立同分布采样而得。
但需注意的是,为了得到“举一反三”的能力,测试集应该尽可能与训练集互斥,即测试样本尽量不在训练集中出现、未在训练过程中使用过。
2.1 留出法
"留出法"直接将数据集D划分为两个互斥的集合,其中一个集合作为训练集S,另一个作为测试集T,即D=S∪T,S∩T=∅。在S上训练出模型后,用T来评估其测试误差,作为对泛化误差的估计。
需注意的是,训练/测试集的划分要尽可能保持数据分布的一致性,避免因数据划分过程引入额外的偏差而对最终结果产生影响。即便在给定训练/测试集的样本比例后,仍存在多种划分方式对初始数据D进行分割。不同的划分将导致不同的训练/测试集,相应的,模型评估的结果也会有所差别。因此单独使用留出法得到的估计结果往往不够稳定可靠,在使用留出法时,一般要采用若干随机划分、重复进行实验评估后取平均值作为留出法的评估结果。
2.2 交叉验证法
“交叉验证法”先将数据集D划分为k个大小相似的互子集,即。每个子集Di都尽可能保持数据分布的一致性,即从D中通过分层采样的到。然后,每次用k-1个子集的并集作为训练集,余下的那个子集作为测试集;这样就可获得k组训练/测试集,从而可进行k次训练和测试,最终返回的是这k个测试结果的均值。下图给出10折交叉验证的示意图
假定数据集D中包含m个样本,若令k=m,则得到了交叉验证法的一个特例:留一法。留一法不受随机样本划分方式的影响,因为m个样本只有唯一的方式划分m个子集(每个子集中包含一个样本)。大多情况下,留一法中被实际评估的模型与期望估计的用D训练出的模型很相似。但当数据集较大时,训练模型的开销也很大。
2.3 自助法
在留出法和交叉验证法中,由于保留了一部分样本用于测试,因此实际评估的模型所使用的训练集比D小,这必然会引入一些因训练样本规模不同而导致的估计偏差。
“自助法”是针对上述缺点的一个比较好的解决方案,它直接以自助采样法为基础。给定包含m个样本的数据集D,我们对它进行采样产生数据集D’:每次随机从D中挑选一个样本,将其拷贝放入D’,然后再将该样本放回初始数据集D中,使得该样本在下次采样时仍有可能被采到;这个过程重复执行m次后,我们就得到了包含m个样本的数据集D’,这就是自助采样的结果。
D中有一部分样本会在D’中多次出现,而另一部分样本不出现。样本在m次采样中始终不被采到的概率是,取极限得到
,即通过自助采样,初始数据集D中约有36.8%的样本未出现在采样数据集D’中。于是我们可将D’用作训练集,D\D’用作测试集;这样,实际评估的模型与期望评估的模型都使用m个训练样本,而我们仍有数据总量约1/3的、没在训练集中出现的样本用于测试。这样的测试结果,也称为“包外估计”。
2.4 调参与最终模型
在进行模型评估与选择时,除了要对使用学习算法进行选择,还需对算法参数进行设定,这就是通常所说的“参数调节”或简称“调参”。
另外,通常把学得模型在实际使用中遇到的数据称为测试数据,为了加以区分,模型评估与选择中用于评估测试的数据集常称为“验证集”。
三、性能度量
对学习器的泛化性能进行评估,不仅需要有效可行的实验估计方法,还需要有衡量模型泛化能力的评价标准,这就是性能度量(performance measure)。
3.1回归任务的性能度量
回归任务最常用的性能度量是“均方误差”
更一般的,对于数据分布D和概率密度函数p(),均方误差可描述为
下面主要介绍分类任务中常用的性能度量
3.2错误率与精度
错误率是分类错误的样本数占样本总数的比例,精度则是分类正确的样本数占样本总数的比例。
对样例集D,分类错误率定义为
精度则定义为
3.3 查准率、查全率和F1
错误率和精度虽常用,但并不能满足所有任务需求。例如在信息检索中,我们经常会关心“检索出的信息有多少比例是用户感兴趣的”“用户感兴趣的信息中有多少被检索出来了”。“查准率”与“查全率”是更为适用于此类需求的性能度量。对于二分类问题,根据其真实类别与学习器预测类别的组合可划分为真正例、假正例、真反例、假反例四个情形,令TP、FP、TN、FN分别表示对应的样例数,TP+FP+TN+FN=样例总数。分类结果的“混淆矩阵”如下表所示。
查准率P与查全率R分别定义为
查准率和查全率是一对矛盾的变量。一般来说,查准率高时,查全率往往偏低;而查全率高时,查准率往往偏低。通常只有在一些简单任务中,才可能使查准率和查全率都很高。
逐个把样本作为正例进行预测,则可以计算出查全率和查准率,分别将它们作为横轴和纵轴,可以得到类似下面的P-R图。
![](https://img-blog.csdnimg.cn/direct/77e33079079f45f4bf0eb48116f0a6da.png)
“平衡点/Break-Event Point”(简称BEP),它是综合考查准率、查全率的性能度量,它是“查准率=查全率”时的取值。
但BEP还是过于简化一些,更常用的是F1度量
在一些应用中,对查准率和查全率的重视程度有所不同。F1度量的一般形式,能让我们表达出对查准率/查全率的不同偏好,它定义为
其中β>0度量了查全率对查准率的相对重要性:①当β=1时, 退化为标准的F1②当β>1 时,对查全率有更大影响③当β<1时,对查准率有更大影响
3.4 ROC与AUC
很多学习器是为测试样本产生一个实值或概率预测,然后将这个预测值与一个分类阈值进行比较,若大于阈值则分为正类,否则为反类。实际上,根据这个实值或预测结果,我们可将测试样本进行排序,“最可能”是正例的排在最前面,“最不可能”是正例的排在最后面,这样,分类过程就相当于在这个排序中以某个“截断点”将样本分为两部分,前一部分判作正例,后一部分则判为反例。
在不同的应用任务中,我们可根据任务需求来采用不同的截断点。例如若我们更重视“查准率”,则可选择排序中靠前的位置进行截断;若更重视“查全率”,则可选择靠后的位置进行截断。因此,排序本身的质量好坏,体现了综合考虑学习器在不同任务下的“期望泛化性能”的好坏,或者说,“一般情况下”泛化性能的好坏。
ROC全称是“受试者工作特征/Receiver Operating Characteristic”,与P-R曲线相似,根据学习器的预测结果对样例进行排序,按此顺序逐个把样本作为正例进行预测,每次计算出两个重要量的值,分别以它们为横、纵坐标作图,就得到了“ROC曲线”。ROC曲线的纵轴是“真正例率/True Positive Rate”(简称TPR),横轴是“假正例率False Positive Rate”(FPR),两者分别定义为:
显示ROC曲线的图称为“ROC图”,如下图图(a),对角线对应于“随机猜测”模型,点(0,1)对应于将所有的正例排在所有反例之前的“理想模型”,现实任务中通常获得如图(b)所示的近似ROC曲线
![](https://img-blog.csdnimg.cn/direct/f17735a8233a40af82df8922c1e39be2.png)
ROC曲线的面积就是AUC(Area Under Curve)。
AUC用于衡量“二分类问题”机器学习算法性能(泛化能力)。参考图(b),AUC可估算为
四、通过实验实现模型评估与性能度量(VS code编辑器)
本次实验实现对KNN的模型评估,通过将随机数据集划分成训练集和测试集,并训练KNN分类器后,计算KNN算法的TP(真正例)、FP(假正例)、TN(真反例)、FN(假反例)后,计算R(查全率)和P(查准率)并绘制对应的P-R曲线,计算FPR(假正例率)和TPR(真正例率)以及AUC并绘制对应的ROC曲线
4.1代码实现
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score, precision_recall_curve, roc_curve, auc
from sklearn.metrics import roc_auc_score
import seaborn as sns
# 生成包含1000个样本的随机数据集
np.random.seed(0)#设置随机数种子为0,确保每次生成的随机数序列相同使结果可重复
X = np.random.rand(1000, 10)#矩阵1000行10列
y = (X[:, 0] + X[:, 1] > 1).astype(int)#根据X的第1列、第2列之和是否大于1来生成对应的标签y
# 划分数据集为训练集(80%)和测试集(20%)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 特征标准化,标准化用于将特征数据转换为具有零均值和单位方差的形式
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)#对训练集进行标准化处理
X_test = scaler.transform(X_test)#对测试集进行标准化处理
# 初始化KNN分类器并选择K值
k = 5
knn_classifier = KNeighborsClassifier(n_neighbors=k)
# 训练KNN分类器
knn = KNeighborsClassifier(n_neighbors=5)
knn.fit(X_train, y_train)
# 模型的概率预测
y_scores = knn.predict_proba(X_test)[:, 1]
# 初始化空列表来存储P-R曲线上的点
precision_points = []#查准率
recall_points = []#查全率
# 初始化空列表来存储ROC曲线上的点
TPR_points = []#真正例率
FPR_points = []#假正例率
# 遍历不同的阈值
thresholds = np.linspace(0, 1, 10)#生成一个包含10个元素的等差数列,范围从0到1
for threshold in thresholds:
y_pred = (y_scores >= threshold).astype(int)
#print("y_pred:",y_pred)
TP = np.sum((y_pred == 1) & (y_test == 1))
FP = np.sum((y_pred == 1) & (y_test == 0))
TN = np.sum((y_pred == 0) & (y_test == 0))
FN = np.sum((y_pred == 0) & (y_test == 1))
TPR = TP / (TP + FN)
FPR = FP / (FP + TN)
TPR_points.append(TPR)
FPR_points.append(FPR)#将计算得到的FPR添加到FPR_points列表中
precision = TP / (TP + FP) if TP + FP > 0 else 1.0
recall = TP / (TP + FN) if TP + FN > 0 else 1.0
precision_points.append(precision)
recall_points.append(recall)
print("TP(真正例个数):",TP)
print("FP(假正例个数):",FP)
print("TN(真反例个数):",TN)
print("FN(假反例个数):",FN)
print("R(查全率):",recall_points)
print("P(查准率):",precision_points)
print("FPR(假正例率):",FPR_points)
print("TPR(真正例率):",TPR_points)
#计算AUC
AUC = roc_auc_score(y_test, y_pred)
print("AUC = ",AUC)
# 绘制P-R曲线
plt.plot(recall_points, precision_points, marker='.')
plt.xlabel('Recall')
plt.ylabel('Precision')
plt.title('P-R Curve')
plt.grid(True)
#plt.show()
# 绘制 ROC 曲线
plt.figure()
plt.plot(FPR_points, TPR_points, color='darkorange', lw=2)
plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate (FPR)')
plt.ylabel('True Positive Rate (TPR)')
plt.title('ROC Curve')
plt.show()
4.2实验结果截图
4.3实验小结
通过学习和实验,我了解了对模型评估的方法以及相关的性能度量,也学习了PR曲线和ROC曲线的绘制方法、常见误区及注意事项。最后,实现了对PR曲线和ROC曲线的应用。
PR曲线和ROC曲线是两种重要的模型评估工具,它们能够为我们提供全面的模型性能视图,帮助我们了解模型在不同阈值设置下的表现。通过绘制PR曲线和ROC曲线,我们可以直观地观察到模型在精确度和召回率之间的平衡关系,以及模型对正负样本的识别能力。对于不同的算法模型,例如在knn算法中改变K值,其准确率、召回率、ROC曲线、AUC等都会发生变化,下图是在本次实验中K值取20的结果图:
在实际应用中,我们应该根据具体问题的特点选择合适的评估指标和方法,以获得更准确的模型评估结果。
五、参考书籍
《机器学习》 周志华
《机器学习实战》 Peter Harrington