目录
(4)真正例率TPR(True Positive Rate)
一、模型评估概述
1.模型评估是什么
- 模型评估是对训练好的模型性能进行评估,模型评估是模型开发过程不可或缺的一部分,有助于我们了解模型的性能和泛化能力。机器学习的任务有回归,分类和聚类,针对不同的任务有不同的评价指标。按照数据集的目标值不同,可以把模型评估分为分类模型评估和回归模型评估。
2.模型评估的作用
- 衡量预测误差:模型评估可以告诉我们模型在预测新数据时的准确度(误差的大小)
- 检测拟合程度:通过评估我们可以判断模型对训练数据的拟合程度,还有是否出现过拟合或欠拟合的情况
- 评估模型稳定性:模型评估可以帮助我们了解模型在不同数据集上的表现是否稳定
- 选择评估指标:根据不同的机器学习任务和应用场景,我们需要选择合适的评估指标来衡量模型的性能。(具体的评估指标在下面介绍)
模型评估不仅是为了衡量模型的性能,更是为了确保模型能够在实际应用中达到预期的效果。通过评估,我们可以进行实验的优化,不断调整和优化模型,保证其泛化能力,直至满足实际应用的需求。
二、常见的分类模型评估指标
1.混淆矩阵
混淆矩阵是用于评估分类模型性能的一个工具,主要用于模型的分类结果和实例的真实信息的比较。
矩阵中的每一行代表实例的预测类别,每一列代表实例的真实类别,具体如下表:
TP(True Positive):真正例,指的是分类器正确预测的正元组数量,即实际为正元组且被预测为正元组的情况。
TN(True Negative):真负例,指的是分类器正确预测的负元组数量,即实际为负元组且被预测为负元组的情况。
FP(False Positive):假正例,指的是分类器错误地将负元组预测为正元组的数量,即实际为负元组但被预测为正元组的情况。
FN(False Negative): 假负例,指的是分类器错误地将正元组预测为负元组的数量,即实际为正元组但被预测为负元组的情况。
在混淆矩阵中,希望TP与TN的数量大,FP与FN的数量小,因此在得到模型的混淆矩阵后,观测值在第二、四象限的越多越好,在第一、三象限的观测值越少越好。
2.评估指标
(1)准确率(Accuracy)
指模型正确预测的样本数占总样本数的比例,是评估模型整体性能最直观的指标。
(2)查准率(Precision)
指在所有被预测为正类别的样本中,实际为正类别的样本所占的比例。
(3)错误率(Error Rate)
与准确率相反,它指的是模型错误预测的样本数占总样本数的比例。
(4)真正例率TPR(True Positive Rate)
又称为查全率或召回率(recall),表示在所有实际为正类别的样本中,被正确预测为正类别的样本所占的比例。
(5)真负例率(特异度Specificity)
在所有实际为负类别的样本中,被正确预测为负类别的样本所占的比例。
(6)F1分数(F-measure)
是查准率和查全率的调和均值,用于同时考虑查准率和查全率,当二者之一较低时,F1分数会降低
3.ROC曲线
- ROC曲线(Receiver Operating Characteristic Curve)是一种用于评估二分类模型性能的图形工具。它以假正例率(False Positive Rate,FPR)为横坐标,真正例率(True Positive Rate,TPR)为纵坐标绘制。在ROC曲线中,横轴代表假正例率,纵轴代表真正例率。
-
(1)假正例率(FPR)
假设为负例的样本中被错误地预测为正例的比率
在ROC曲线中,横轴和纵轴的取值范围都是[0,1]。ROC曲线下的面积被称为AUC(Area Under the Curve),AUC的值越接近1,说明模型性能越好。
4.PR曲线
- PR曲线(Precision-Recall Curve)以精确率(Precision)为横坐标,召回率(Recall)为纵坐标绘制。在PR曲线中,横轴代表精确率,纵轴代表召回率。 PR曲线相比于ROC曲线更适用于正例非常少或者我们关注的是正例的情况
5.ROC曲线与PR曲线的差异
- ROC曲线适用于不同类别样本的分布比较均匀的情况下,能够很好地反映出分类器的整体性能,对于类别不平衡的问题不太敏感。当测试集中的正负样本的分布发生变化的时候,ROC曲线能够保持稳定。而在PR曲线中,选择不同的测试集,P-R曲线的变化会非常大。这个特点让ROC曲线能够尽量降低不同测试集带来的干扰,更加客观地衡量模型本身的性能。
- PR曲线更适用于类别不平衡的情况下,在正负样本分布得极不均匀,负例远大于正例时,并且这正是该问题正常的样本分布时,比ROC能更有效地反应分类器的好坏,即PR曲线在正负样本比例悬殊较大时更能反映分类的真实性能。
三、绘制ROC曲线
1.加载鸢尾花数据集
from sklearn import datasets
import pandas as pd
import numpy as np
iris = datasets.load_iris() #Loading the dataset
print(iris.keys())
# dict_keys(['data', 'target', 'frame', 'target_names', 'DESCR', 'feature_names', 'filename', 'data_module'])
- 导入datasets模块,此模块中有很多常用的数据集,鸢尾花数据集直接在里面导入即可
- iris = datasets.load_iris(): 这行代码使用datasets模块中的load_iris()函数来加载鸢尾花数据集,加载后的数据被赋值给变量iris
- iris.keys(): 这行代码调用了iris数据集的keys()方法,返回了一个包含数据集的键(key)的列表。这些键表示数据集的不同方面。返回的键包括:
- 'data': 包含样本数据的numpy数组。
- 'target': 包含每个样本对应的目标类别(0、1、2)的numpy数组。
- 'frame': 数据集的一个备用表示,通常不会使用。
- 'target_names': 目标类别的名称。
- 'DESCR': 数据集的描述文本,包括数据集的来源和特征描述等信息。
- 'feature_names': 特征的名称。
- 'filename': 数据集文件的路径(如果适用)。
- 'data_module': 数据集的Python模块路径。
#创建了一个DataFrame,其中包含了鸢尾花数据集的所有样本数据以及目标类别
iris = pd.DataFrame(
data=np.c_[iris['data'], iris['target']],
columns=iris['feature_names'] + ['target']
)
#将鸢尾花数据集(iris dataset)中的目标值(target)转换为对应的鸢尾花品种名称,并将结果存储在新的一个名为 species 的列表中。
species = []
for i in range(len(iris['target'])):
if iris['target'][i] == 0:
species.append("setosa")
elif iris['target'][i] == 1:
species.append('versicolor')
else:
species.append('virginica')
iris['species'] = species
#使用Pandas 库中的 groupby() 函数,针对鸢尾花数据集(iris dataset)中的 species 列进行分组,并计算每个品种出现的次数。具体来说,代码执行后将返回一个包含各个品种及其对应出现次数的 Series 对象。
iris.groupby('species').size()
#针对鸢尾花数据集(iris dataset)的数值列进行统计分析
iris.describe()
- 解释附在上面代码注释中了
2. 分割数据集
from sklearn.model_selection import train_test_split
X = iris.drop(['target','species'], axis=1)
X = X.to_numpy()[:, (2,3)]
y = iris['target']
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.5, random_state=42)
- 导入必要的库:首先,代码导入了从 scikit-learn 库中的 train_test_split 函数,这个函数用于将数据集分割成训练集和测试集。
- 特征和标签的准备:代码从鸢尾花数据集中移除了 ‘target’ 列和 ‘species’ 列,因为只需要花的测量数据作为特征。这一步骤是为了获取仅包含花瓣长度和花瓣宽度这两个特征的数据。然后,通过 .to_numpy() 方法将特征转换为 NumPy 数组,并提取出特征矩阵 X,其中只包含了第 2 列(花瓣长度)和第 3 列(花瓣宽度)的数据。
- 标签的准备:将原始数据集中的 ‘target’ 列作为标签数组 y。这个数组包含了鸢尾花的分类标签,用来表示花的种类。
- 数据集分割:使用 train_test_split 函数,将特征矩阵 X 和标签数组 y 分割成训练集和测试集。具体来说,代码设置了测试集的大小为 50%(test_size=0.5),并且使用了随机种子 random_state=42,以确保随机划分的结果可重复。
- 分割结果:分割后的结果是四个数组:X_train 包含训练集的特征数据,X_test 包含测试集的特征数据,y_train 包含训练集的标签数据,y_test 包含测试集的标签数据。
将数据集分割成训练集和测试集有利于以后使用这些数据来训练模型并进行性能评估
3.ROC曲线
#定义KNN分类
def knn_classifier(k_value):
knn = KNN(k=k_value)
knn.fit(train_X, train_y)
result = knn.predict(test_X)
return result
#计算不同k值下的准确度
k_values = [1, 3, 5, 7, 9]
for k in k_values:
result = knn_classifier(k)
accuracy = accuracy_score(test_y, result)
print(f"Accuracy for k={k}: {accuracy}")
#开始绘制ROC图像了
plt.figure(figsize=(10, 6))
for k in k_values:
result = knn_classifier(k)
fpr, tpr, thresholds = roc_curve(test_y, result, pos_label=2)
roc_auc = auc(fpr, tpr)
plt.plot(fpr, tpr, lw=2, label='ROC curve (k=%d, area = %0.2f)' % (k, roc_auc))
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')
plt.ylabel('True Positive Rate')
plt.title('ROC Curve for Different k Values')
plt.legend(loc="lower right")
plt.show()
- 这里主要展示的是ROC曲线绘制及计算准确度的代码,对于knn方法的初始化等等就没有展示了
实验结果:
结果分析: 根据本实验的实验结果,可以看出在Iris数据集上使用k-近邻算法进行分类时,不同的k值对准确率没有显著影响, 但需要注意的是在不同实验种不同k值下的ROC曲线可能会有所不同,同时k值对准确率和ROC曲线都有影响。
四、实验总结
虽然在鸢尾花实验中k值对准确率和ROC曲线并无显著影响,但我们需要知道,在不特定问题中,较小的k值意味着模型会更加复杂,因为它更多地依赖于训练数据中的局部结构。这可能导致模型对训练数据过拟合,从而在测试数据上的表现不佳。选择k值对knn算法的性能有很大的影响,在实际问题中应该选择合适的k值,以达到训练模型的最优效果使模型得到很好的泛化能力,这才达到模型评估的目的。