【机器学习】 KNN算法及模型评估

目录

2.1 KNN算法概述

      2.1.1 基本概念

2.1.2  准备:使用python导入数据

2.1.3  实施KNN分类算法

2.2  KNN中的距离计算

2.3  KNN算法实例

             2.3.1收集数据:

             2.3.2  准备数据:从文本文件中解析数据

             2.3.3  分析数据:使用Matplotlib创建散点图

             2.3.4  准备数据:归一化数值

             2.3.5  测试算法:作为完整程序验证分类器

             2.3.6  使用算法:构建完整可用系统

             2.3.7结果图呈现

                 结果分析: 

1.实验对比:

2.准确率分析:

3.散点图分析:

2.4 模型评估

2.4.1  常见的分类模型评估指标以及如何计算

2.4.2ROC曲线和PR曲线

1.ROC曲线

2.PR曲线

3.两者之间的差异 

2.4.3添加了不同k值下的ROC曲线的代码

1、代码分析:

2、关于ROC曲线的运行结果图:

2.5总结:

      1. KNN算法

      2.ROC曲线以及模型改进

     3.内容补充



2.1 KNN算法概述

      2.1.1 基本概念

               简单来说,KNN算法是一种基本的分类与回归方法,它的核心思想是通过找出与待分类样本最近的K个训练样本,然后根据这K个样本的类别进行决策。一般流程如下:

            (1)收集数据:可以使用任何方法。
            (2)准备数据:距离计算所需要的数值,最好是结构化的数据格式。
            (3)分析数据:可以使用任何方法。
            (4)训练算法:此步骤不适用于KNN算法。
            (5)测试算法:计算错误率。
            (6)使用算法:首先需要输入样本数据和结构化的输出结果,然后运行KNN算法判定输入数据分别属于哪个分类,最后应用对计算出的分类执行后续的处理。

KNN算法的优缺点有如下:

              1. KNN算法的优点:
               高精度:在许多情况下,k-近邻算法能够提供较高的分类精度。
               对异常值不敏感:由于分类决策是基于多个最近邻样本的投票结果,因此单个异常值对于分类结果的影响较小。
               无需数据分布假设:k-近邻算法不需要假设数据的分布情况,适用于各种不同类型的数据集。

               2. KNN算法的缺点:
               计算复杂度高:对于每个新样本,需要计算其与训练样本集中所有样本之间的距离,因此计算量较大。
               空间复杂度高:需要存储整个训练样本集,因此需要较大的内存空间。

2.1.2  准备:使用python导入数据

               1.创建名为KNN.py的python模板
               2.导入必要的库
               3.读取数据文件
               4.提取特征和标签
               5.划分训练集和测试集
               6.数据预处理

2.1.3  实施KNN分类算法

          伪代码如下:
                (1)计算已知类别数据集中的点与当前点之间的距离;
                (2)按照距离递增次序排序;
                (3)选取与当前点距离最小的k个点;
                (4)确定前k个点所在类别的出现频率;
                (5)返回前k个点出现频率最高的类别作为当前点的预测分类。

2.2  KNN中的距离计算

                 一般使用欧氏距离:d(x, y) = sqrt((x1 - y1)^2 + (x2 - y2)^2 + ... + (xn - yn)^2)

2.3  KNN算法实例

             2.3.1收集数据:

             2.3.2  准备数据:从文本文件中解析数据

             2.3.3  分析数据:使用Matplotlib创建散点图

             2.3.4  准备数据:归一化数值

             2.3.5  测试算法:作为完整程序验证分类器

             2.3.6  使用算法:构建完整可用系统

import pandas as pd
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score

plt.rcParams['font.sans-serif'] = ['SimHei']  # 设置字体为中文黑体
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号

# 2.3.1 准备数据:从文本文件中解析数据
data = pd.read_csv('roses_data.csv')
X = data[['花瓣长度', '花瓣宽度']]
y = data['品种']

# 2.3.2 分析数据:使用Matplotlib创建散点图
plt.figure(figsize=(8, 6))  # 设置图形大小
plt.scatter(data['花瓣长度'], data['花瓣宽度'], c=data['品种'].map({'山茶花': 'red', '月季花': 'blue', '玫瑰花': 'green'}))
plt.xlabel('花瓣长度')
plt.ylabel('花瓣宽度')
plt.title('花朵数据集')

# 添加数据标签
for i, row in data.iterrows():
    plt.annotate(row['品种'], (row['花瓣长度'], row['花瓣宽度']))

# 设置坐标轴范围
plt.xlim(0, 7)  # 设置x轴范围为0到10
plt.ylim(0, 3)   # 设置y轴范围为0到6

plt.show()

# 2.3.3 准备数据:归一化数值
scaler = MinMaxScaler()
X_normalized = scaler.fit_transform(X)

# 2.3.4 测试算法:作为完整程序验证分类器
X_train, X_test, y_train, y_test = train_test_split(X_normalized, y, test_size=0.2, random_state=42)
knn = KNeighborsClassifier(n_neighbors=3)  # 调整K值为3
knn.fit(X_train, y_train)
y_pred = knn.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print("准确率:", accuracy)

             2.3.7结果图呈现

                 结果分析: 

       首先,需要从文本文件中解析数据,然后使用Matplotlib创建散点图来分析数据。接下来,再将数据归一化,并将数据集划分为训练集和测试集。最后,使用KNN算法进行训练和预测,并计算准确率。

1.实验对比:

k=3:

k=10:

2.准确率分析:

     如果准确率较高,说明KNN算法在这个数据集上表现较好;如果准确率较低,可能需要调整KNN算法的参数或尝试其他分类算法。此外,我们还可以通过观察散点图来了解数据集中不同品种的分布情况,以及花瓣长度和宽度之间的关系。

3.散点图分析:

       通过观察散点图,我们可以了解数据集中不同品种的分布情况,以及花瓣长度和宽度之间的关系。散点图中不同颜色的点代表不同的品种,横轴表示花瓣长度,纵轴表示花瓣宽度

2.4 模型评估

2.4.1  常见的分类模型评估指标以及如何计算

  1. 混淆矩阵:提供了模型预测结果的详细视图,包含真正例(TP)、假负例(FN)、假正例(FP)和真负例(TN)四个元素。其中对于二分类问题,该混淆矩阵如下所示:

    预测为正类别预测为负类别
    真实正类别TPFN
    真实负类别FPTN
  2. 准确率:

    • 准确率是分类器正确分类的样本数占总样本数的比例
    • 计算公式:准确率 = (TP + TN) / (TP + TN + FP + FN) 
  3. 精确率:

    • 精确率是分类器预测为正类别的样本中,真正为正类别的比例
    • 计算公式:精确率 = TP / (TP + FP) 
  4. 错误率:

         1. 错误率是分类器错误分类的样本数占总样本数的比例
         2.计算公式:错误率 = (FP + FN) / (TP + TN + FP + FN)

  5. 召回率:

    • 召回率是真实为正类别的样本中,被分类器正确预测为正类别的比例
    • 计算公式:召回率 = TP / (TP + FN) 
  6. F1 值:

    • F1 值是精确率和召回率的调和平均数,综合考虑了精确率和召回率。
    • 公式:F1 = 2 * (精确率 * 召回率) / (精确率 + 召回率)
  7. ROC曲线:描绘了不同阈值下的真正例率和假正例率之间的关系。
  8. AUC:计算ROC曲线下的面积,用来量化地比较不同模型的性能。AUC值越高,说明模型的性能越好。 

2.4.2ROC曲线和PR曲线

1.ROC曲线

  • 定义:ROC曲线描绘了不同判定阈值下的真正例率(TPR,即召回率)和假正例率(FPR)之间的关系。
  • 横轴:假阳率,计算公式为 FPR = FP / (FP + TN),表示被错误分类为正类别的负样本占所有负样本的比例。
  • 纵轴:召回率,计算公式为 TPR = TP / (TP + FN),表示正确分类为正类别的正样本占所有正样本的比例。
  • 绘制:通过改变分类器的判定阈值,我们可以得到一系列(TPR, FPR)点,连接这些点就形成了ROC曲线。
  • 特点
               1.ROC曲线下的面积(即AUC)可以用来衡量模型的整体性能,AUC值越高,模型的性能越好。
               2.对于ROC曲线当一个曲线被另一个曲线完全包含了,则后者性能优于前者。

2.PR曲线

  • 定义:其中P为精准率,R为召回率,所以P-R曲线是反映了准确率与召回率之间的关系,一般其X轴是召回率,Y轴是精准率
  • 横轴:召回率,计算公式为 R= TP / (TP + FN),表示正确分类为正类别的正样本占所有真实正样本的比例。
  • 纵轴:精准率,计算公式为 P= TP / (TP + FP),表示被分类为正类别的样本中,真正为正类别的比例。
  • 绘制:首先需要将预测结果按照预测为正类的概率值排序,然后逐步降低概率阈值,从1开始逐渐减小,每次计算出当前的精确率值和召回率值,然后再将这些点以精确率为Y轴,召回率为X轴绘制,最后将所有点连成曲线,从而构成PR曲线。
  • 特点
               1.曲线越靠近右上方,性能越好
               2.当一个曲线被另一个曲线完全包含了,则后者性能优于前者
               3.如果曲线发生交叉时,根据曲线下方面积大小判断,面积更大的更优于面积小的

3.两者之间的差异 

       (1)ROC曲线本质上是正样本或者负样本召回率计算,因此不受样本分布的影响。但是PR曲线由于涉及到精确率计算,故容易受到样本分布的影响。
       (2)当正负样本数量很不均衡时,ROC曲线能够稳定地反映模型本身的好坏,但PR曲线的变化却会非常大,故此时用PR曲线更加能反映出分类器性能的好坏。

2.4.3添加了不同k值下的ROC曲线的代码

from sklearn.metrics import roc_curve
from sklearn.metrics import auc
import matplotlib.pyplot as plt

# 不同 k 值下的 ROC 曲线
k_values = [3, 5, 10, 15]  # 不同的 k 值
plt.figure(figsize=(8, 6))

#  绘制不同k值下的KNN分类器的ROC曲线
for k in k_values:
    knn = KNeighborsClassifier(n_neighbors=k)
    knn.fit(X_train, y_train)
    y_scores = knn.predict_proba(X_test)
    y_scores = y_scores[:, 1]  # 取出正例的概率作为预测分数
    fpr, tpr, _ = roc_curve(y_test, y_scores, pos_label='玫瑰花')
    roc_auc = auc(fpr, tpr)
    plt.plot(fpr, tpr, label='k=%d, AUC=%.2f' % (k, roc_auc))

#  使用Matplotlib库绘制了一个ROC曲线
plt.plot([0, 1], [0, 1], color='darkorange', linestyle='--')
plt.xlabel('False Positive Rate')   # 设置了x轴的标签为"False Positive Rate"(假阳性率)
plt.ylabel('True Positive Rate')   # 设置了y轴的标签为"True Positive Rate"(真阳性率)
plt.title('ROC 曲线')
plt.legend()
plt.show()

1、代码分析:

(1)首先,导入了必要的库和函数:roc_curve用于计算ROC曲线的FPR和TPR,auc用于计算曲线下的面积(AUC),matplotlib.pyplot用于绘图;
(2)然后,定义了一个列表k_values,其中包含了不同的k值( 3、5、10、15 );
(3)然后,针对每个 K 值,计算对测试集的预测概率,提取正例的概率作为预测分数;
(4)然后,利用 roc_curve 函数计算每个 K 值下的 FPR 和 TPR,并计算 AUC;
(5)最后,绘制 ROC 曲线,展示不同 K 值下的分类器性能,并标注对应的 AUC 值,并且在绘制完所有k值的ROC曲线后,使用plt.plot函数绘制了一条对角线,表示随机分类器的ROC曲线。

2、关于ROC曲线的运行结果图:

已知曲线下的面积AUC越接近0.5,表示模型的性能越差;AUC越接近1,表示模型的性能越好,故上述ROC曲线分析有:

(1)随着k值的增加,ROC曲线整体上呈现出上升的趋势,意味着随着k值的增加,分类器对于正例的预测能力逐渐增强
(2)k值为3时,AUC值为0.12,这是一个相对较低的值,意味着分类器的性能不佳。
(3)  k值为5时,AUC值为0.20,比起k=3较好些,在相同的FPR下有更高的TPR,说明增加了邻居数量后,分类器对正例样本的识别能力有所提高
(4)k值为10时,AUC值为0.20,和k值为5一样,但是此时更多的邻居被考虑在内,有助于更准确地分类样本
(5)k值为15时,AUC值为0.22,是这几条线中最高的,表明分类器的性能最好,这说明了分类器在较大的k值下表现较好,相对而言能够更好地区分正例和负例
 

2.5总结:

      1. KNN算法

       KNN算法是一种基于实例的学习算法,它通过计算待分类样本与训练集中的样本之间的距离来确定其类别,在上述代码中我们使用了KNN算法对花朵数据集进行分类。但KNN算法的性能会受到距离度量、邻居数量等因素的影响。因此,在实际应用中,我们需要根据具体情况选择合适的参数,并进行调优。

      2.ROC曲线以及模型改进

       通过后面ROC曲线图像和描述的分析,我发现该KNN模型存在一些不足之处:其不同k值的AUC值都太低了,该模型没有很好的学习到数据的一些特征,因此,我又重新去修改数据,如下图是修改数据后的ROC曲线图,可以看出相对于前面的ROC曲线图,其AUC值变高了。

         图像解释:

                (1)当k值=3时,即使AUC值为0.71属于分类器的性能是比较好的,但是当ROC曲线接近于y轴时,会发现此时在较低的FPR值下,TPR值并不高,即真正例率不高而假正例率较高。这会导致很多实际为负例的样本被预测为正例。故说明当k=3时,在这些特定阈值下的性能不是最佳。

                (2)当k值=5时,AUC值为0.61,这意味着模型在整个可能的阈值范围内,能够比较好地区分正类和负类。

                (3)当k值=10时,AUC值为0.54,这意味着分类器的性能比较差。

                (4)当k值=15时,AUC值为0.89,并且在较低的FPR值下就能达到较高的TPR,这代表了模型在这些特定的阈值下就可以具有较好的性能,故在这四个k值中,k=15时分类器性能最佳。

     3.内容补充

(修改后的数据集部分截图及其散点图)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值