数据挖掘 K近邻

什么时候用K近邻?
交叉验证的时候。最常见的交叉验证方法是K折交叉验证,其中数据集被均匀分成K个子集,称为折,然后执行K次训练和测试,每次选择不同的折作为测试集,其余的作为训练集。最后,将K次测试结果的平均值作为模型的性能指标。

什么叫交叉验证?
交叉验证是一种常用的模型评估技术,用于评估机器学习模型的性能和泛化能力。在机器学习中,我们通常希望评估训练好的模型对未见过数据的表现情况,以确保模型可以泛化到新的数据上。

交叉验证的基本思想?
交叉验证的基本思想是将原始数据集分成若干个子集,然后进行多轮训练和测试。在每一轮中,选择一个子集作为测试集,其余子集作为训练集,然后训练模型并在测试集上进行评估。

交叉验证的子集会重复使用吗?
当K等于原始数据集大小时,这种交叉验证方法称为留一法(Leave-One-Out,简称LOO),即每个样本都被用作测试集一次,其余样本用于训练模型。在这种情况下,子集不会重复使用。但是,LOO计算代价较高,并且可能过度拟合训练数据,因此通常不是首选的交叉验证方法。总之,交叉验证中的子集会重复使用,以确保我们可以评估模型在不同数据集上的性能,并减少因数据集划分不合理而引入的偶然性。

K近邻通常用哪些头文件?

# 导入pandas和numpy库
import pandas as pd
import numpy as np
# 导入sklearn库中的KNeighborsClassifier
from sklearn.neighbors import KNeighborsClassifier
# 导入os库
import os
# 导入sklearn库中的GridSearchCV
from sklearn.model_selection import GridSearchCV

K近邻的头文件都是什么,都有什么用?
第一、二行:
数据处理库pandas和科学计算库numpy。通过这两个库,您可以进行各种数据操作和分析。一般来说,习惯上将pandas重命名为pd,numpy重命名为np,以方便在代码中使用。导入这两个库后,您可以使用它们提供的函数和方法进行数据读取、数据处理、数据分析等操作。例如,使用pandas的read_csv()函数读取CSV文件,使用numpy的array()函数创建数组等。
第三行:
from sklearn.neighbors import KNeighborsClassifier: 这一行代码导入了scikit-learn库中的KNeighborsClassifier类。K近邻分类器是一种基于实例的学习算法,通过基于最近邻居的投票来进行分类。
第四行:
import os: 这一行代码导入了Python的os模块,用于与操作系统进行交互,例如获取文件路径、创建目录等操作。
第五行:
from sklearn.model_selection import GridSearchCV: 这一行代码导入了scikit-learn库中的GridSearchCV类。GridSearchCV是一种用于自动化调优模型参数的方法,它会自动尝试不同的参数组合,并选择最佳参数组合以获得最佳模型性能。
综上所述:
这几个导入语句主要用于机器学习中的分类任务和参数调优操作。其中,KNeighborsClassifier用于构建K近邻分类器模型,os模块用于与操作系统进行交互,GridSearchCV用于自动化调优模型参数。这些工具可以帮助您更方便地进行机器学习模型的开发和优化。

具体案例-手写数字识别:

# 导入pandas和numpy库
import pandas as pd
import numpy as np
# 导入sklearn库中的KNeighborsClassifier
from sklearn.neighbors import KNeighborsClassifier
# 导入os库
import os
# 导入sklearn库中的GridSearchCV
from sklearn.model_selection import GridSearchCV

# 获取训练数据路径
Train_data_path = os.listdir("./digits/trainingDigits")  # os.listdir返回的是目录中所有的文件和文件夹的名称,而不包括子目录中的内容。
# 初始化训练集X和Y
Train_X = []
Train_Y = []
# 遍历训练数据路径
for data_file in Train_data_path:
    # 获取训练数据标签
    data_file.split("_")
    # data_file.split("_")会将文件名按照"_"进行分割,得到一个由多个字符串组成的列表,如["digit", "0.txt"]。
    # 通过索引[0]取出列表中的第一个元素"digit",即数据文件对应的标签部分。
    # Train_Y.append() 将提取出的标签部分添加到 Train_Y 列表中。这样,每次执行这段代码,Train_Y 列表都会逐步积累包含各个数据文件标签的元素。最终 Train_Y 列表可能会包含类似 ["digit", "digit", ...] 的内容,其中每个元素对应一个数据文件的标签信息。
    Train_Y.append(data_file.split("_")[0])
    # 打开训练数据文件
    with open(f"./digits/trainingDigits/{data_file}", "r") as f:  # 建议别用open,用numpy.load(),因为老师真的会喷
        # 读取训练数据
        num = f.read().replace("\n", '')  # 将无敌的换行符替换为空字符串,并所有数据转化为一个很长的字符串
        # 初始化x
        x = []
        # 遍历训练数据
        for i in num:
            # 将训练数据转换为整数
            x.append(int(i))  # x 列表中包含了训练数据中每个数字所对应的像素点信息,这些信息都以整数形式存储在列表中
        # 将x添加到训练集X中
        Train_X.append(x)  # 通过添加操作,我们可以将所有的训练数据都存储在 Train_X 列表中,并且可以通过索引访问列表中的每个子列表来获取对应数字的像素点信息。
        # 打印x
        # print(x)
        # 打印x的长度
        # print(len(x))

# 获取测试数据路径
Test_data_path = os.listdir("./digits/testDigits")
# 初始化测试集X和Y
Test_X = []
Test_Y = []
# 遍历测试数据路径
for data_file in Test_data_path:
    # 获取测试数据标签
    Test_Y.append(data_file.split("_")[0])
    # 打开测试数据文件
    with open(f"./digits/TestDigits/{data_file}", "r") as f:
        # 读取测试数据
        num = f.read().replace("\n", '')
        # 初始化x
        x = []
        # 遍历测试数据
        for i in num:
            # 将测试数据转换为整数
            x.append(int(i))
        # 将x添加到测试集X中
        Test_X.append(x)
        # 打印x
        # print(x)
        # 打印x的长度
        # print(len(x))

# 定义参数网格
# list(range(1, 12)) 是一个列表,包含了从 1 到 11(不包括 12)的整数。这个列表是作为字典的值存储的,表示 K最近邻(K-Nearest Neighbors,KNN)需要测试的邻居数的范围。range(1, 12) 包含了从 1 到 11 的整数,因此 KNN 算法将会尝试从 1 到 11 的不同邻居数,来确定最佳的邻居数。也就是说,算法将会尝试使用 1 个邻居、2 个邻居、3 个邻居......直到 11 个邻居来进行分类。
param_grid = {'n_neighbors': list(range(1, 12))}
# 初始化KNeighborsClassifier
clf = KNeighborsClassifier()  # 创建了一个 KNN(K-最近邻)分类器对象
# 使用GridSearchCV对KNeighborsClassifier进行参数搜索
# GridSearchCV 是 sklearn 库中用于执行网格搜索和交叉验证的类。它接受三个参数:
# clf:要使用的分类器对象,这里传入了之前创建的 KNN 分类器对象 clf。
# param_grid:一个字典,表示要搜索的参数空间。这里传入了之前定义的 param_grid 字典,用于指定 KNN 算法中的邻居数的范围。
# cv:整数或交叉验证迭代器,表示进行交叉验证的折数。这里设置为 10,表示使用 10 折交叉验证。老登说10折好用,有理论基础。
GS_model = GridSearchCV(clf, param_grid, cv=10)
# 对训练集进行参数搜索
GS_model.fit(Train_X, Train_Y)
# 打印最优参数和最优配置
# GS_model.best_params_:最佳的邻居数
# GS_model.best_score_:模型在训练数据集上分类正确的比例
print(f'模型的最优参数最优配置为{GS_model.best_params_},且训练精度为{GS_model.best_score_:.3f}')

# 初始化最优模型
# 创建了一个 K 最近邻分类器(KNeighborsClassifier)的实例 Best_model,并使用了之前通过网格搜索得到的最佳参数配置中的最优邻居数量 'n_neighbors' 来初始化这个分类器。
Best_model = KNeighborsClassifier(GS_model.best_params_['n_neighbors'])
# 对训练集进行训练
Best_model.fit(Train_X, Train_Y)
# 计算测试集的分类精度
score = Best_model.score(Test_X, Test_Y)
# 打印测试集的分类精度
print(f'交叉验证得到模型的测试分类精度为{score:.3f}')
# 这段代码使用了一个循环来尝试不同的K值,然后训练KNN模型并输出每个K值对应的预测得分。这种方法可以帮助你找到最适合数据集的K值,从而提高模型的性能。在循环中,首先创建了一个KNN模型,并使用当前的K值进行初始化。然后,使用训练数据对模型进行训练,并计算模型在测试数据上的得分。最终,打印出每个K值对应的模型得分。通过这种方式,你可以比较不同K值下模型的性能表现,以便选择最佳的K值来构建最终的KNN模型。
# for i in range(1,11):
#     model = KNeighborsClassifier(i)
#     model.fit(Train_X,Train_Y)
#     print(f"当K等于{i}时模型预测得分为:",model.score(Test_X,Test_Y))

# K最近邻(K-Nearest Neighbors,KNN)算法是一种常用的监督学习方法,用于解决分类和回归问题。在KNN算法中,对于一个给定的未知数据点,根据其在特征空间中与其他已知数据点的距离来进行分类或回归预测。KNN算法的基本思想是,如果一个样本在特征空间中的k个最近邻中的大多数属于某个类别,则该样本也属于这个类别。在分类问题中,KNN算法会将未知数据点分配给与其最近邻居所属类别相同的类;在回归问题中,KNN算法会根据最近邻居的值来预测未知数据点的数值。KNN算法的优点之一是简单易理解,易于实现。然而,KNN算法的缺点包括对大规模数据集的计算成本较高,以及在处理高维数据时可能受到“维度灾难”的影响。在实际应用中,可以通过交叉验证等方法来选择最佳的K值,以及使用特征缩放等技术来提高KNN算法的性能。

结果:
在这里插入图片描述
有点小尬,但确实精度提高了,可能这个数据比较符合两种算法吧

让我们看一下下一个案例-海伦K近邻的头文件:

import pandas as pd
import numpy as np
from sklearn.model_selection import GridSearchCV
from sklearn import preprocessing
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import cross_val_score

上面的头文件都是干嘛的呀?
pandas:pandas是一个数据处理和分析的库,提供了高效的数据结构和数据分析工具。通过pandas,你可以轻松地读取、处理和操作数据,例如加载数据集、数据清洗、特征选择等。
numpy:numpy是Python中用于科学计算的一个核心库,提供了高性能的多维数组对象和各种数学函数。在机器学习中,常使用numpy来处理和操作数组数据,例如矩阵运算、向量化操作等。
sklearn.model_selection.GridSearchCV:GridSearchCV是scikit-learn(sklearn)库中的一个模型选择工具,用于通过交叉验证来调整模型的超参数。通过GridSearchCV,你可以定义一个参数网格,它会自动尝试不同参数组合,并选择最佳的参数配置。
sklearn.preprocessing:sklearn.preprocessing是scikit-learn库中的一个数据预处理模块,提供了一系列用于数据预处理的函数和类。这些函数和类可以用来对数据进行缩放、归一化、标准化等操作,以便更好地适应机器学习模型的要求。
sklearn.neighbors.KNeighborsClassifier:KNeighborsClassifier是scikit-learn中的一个K近邻分类器模型。它是基于最近邻算法的一种分类器,用于解决分类问题。KNeighborsClassifier可以根据邻居的类别来预测未知数据点的类别,并具有简单易用的接口。
sklearn.model_selection模块中的cross_val_score函数用于执行交叉验证并计算模型的评分。它可以帮助你评估机器学习模型的性能。

对了,说句题外话,crtl+z撤销,ctrl+shift+z还原
批量注释:ctrl+/ ,取消批量注释: ctrl+/
批量缩进:tab ,取消批量缩进:shift+tab

import pandas as pd
import numpy as np
from sklearn.model_selection import GridSearchCV
from sklearn import preprocessing
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import cross_val_score

# 读取数据
df = pd.read_csv("datingTestSet.txt", sep="\t",
                 names=['每年获得的飞行常客里程数', '视频游戏所耗时间百分比', '每周消费的冰淇淋公升数', '喜爱程度'])
# print(df.head())#使用df.head()函数来查看数据集的前几行,以确保数据已正确加载。
# 将最后一列数据进行归一化处理
X = preprocessing.MinMaxScaler().fit_transform(df.iloc[:, :-1])
# iloc函数是pandas库中用于按照位置索引选取数据的函数。
Y = df.iloc[:, -1]
# 定义参数网格
param_grid = {'n_neighbors': np.arange(1, 10,
                                       1)}  # param_grid定义了一个名为n_neighbors的超参数,它是KNN算法中k值(即最近邻居数)的取值范围。具体来说,np.arange(1, 10, 1)函数生成了一个从1到9的整数序列,其中步长为1,作为n_neighbors超参数的所有可能取值。也就是说,我们将在这个范围内寻找最佳的k值,以获得最好的模型性能。
# 定义KNN模型
clf = KNeighborsClassifier()
# 使用网格搜索模型
GS_model = GridSearchCV(clf, param_grid, cv=10)
# 训练模型
GS_model.fit(X, Y)
# 输出模型的最优参数最优配置以及训练精度
print(f'模型的最优参数最优配置为{GS_model.best_params_},且训练精度为{GS_model.best_score_:.3f}')

Max_score = 0.0
# 定义KNN模型,找到最佳的K值
for K in range(1, 11):
    model = KNeighborsClassifier(K)
    model.fit(X, Y)
    # 十折验证  #求出其10折平均值
    score = cross_val_score(model, X, Y, cv=10).mean()
    if Max_score < score:
        Max_score = score
        Best_K = K
print("最好的K值为:", Best_K, "平均得分为:", Max_score)

# 定义KNN模型
model = KNeighborsClassifier(Best_K)
# 训练模型
model.fit(X, Y)
# 测试样例
print(model.predict([[0.33193158, 0.41660188,
                      0.24523407]]))  # 输出结果['largeDoses']表示模型对输入的样本[0.33193158, 0.41660188, 0.24523407]进行了分类预测,并将其归类为"largeDoses"。在一些分类问题中,类别可能被编码为字符串形式,而不是数值。类别的具体含义取决于你的具体应用场景。例如,在某个社交网络应用中,"largeDoses"可能代表用户对某种活动的兴趣程度;在医疗诊断中,"largeDoses"可能代表患者疾病的严重程度等等。

# 使用fit_transform函数进行拟合和转换操作。在拟合过程中,它会根据数据集中的最小值和最大值来计算每个特征的转换规则,然后将数据按照这些规则进行转换。具体地,它会将数据缩放到给定的特征范围内,通常是0到1之间。这个函数的作用是将数据集进行归一化,使得不同特征的取值范围都在相同的尺度上,避免了某些特征由于数值范围的差异而对建模产生较大的影响。这样,在进行后续的机器学习模型训练时,各个特征的权重更平衡,提高了模型的稳定性和准确性。总结起来,fit_transform函数的作用就是对数据进行归一化处理,并返回归一化后的结果。

# 这段代码会报错,添加for item in s.items(),通过使用items()函数,你可以避免未来版本中对iteritems()函数的移除所带来的问题。

结果:
在这里插入图片描述
上下代码是一样的,上面是学生写的,下面是老登写的

你可能感兴趣的:(数据挖掘,人工智能)