K-近邻算法实验报告

K-近邻算法实验

实验目的

(1)了解K-近邻算法的相关概念及含义;
(2)掌握K-近邻算法求解问题的流程;
(3)能够编写出K-近邻算法求解某一问题的代码;
(4)能够分析实验结果,对算法进行评估。

实验内容
该实验内容包括以下三部分:

(1)需要对K-近邻算法的相关概念进行阐述;

(2)需要任选一个数据集(Sklearn自带数据集、自动生成数据集、爬虫得来的数据集、各大竞赛平台下载的数据集、来自实际生活的数据集等均可)。
阐述所选定的数据集(该数据集是关于什么的数据集,各个特征表达的含义,标签的含义等等)。

(3)设计实验方案,进行仿真和预测(主要包含:导包、导入数据集、特征和标签的提取、训练集和测试集的划分、特征处理(根据实际情况可选)、K-近邻算法对象的创建、在训练集上进行学习、在测试集上进行预测)。

实验任务书

算法的描述,数据集的描述:
算法是k近邻算法,参数的选择上,最后选择的综合效果最好的是:用的距离为9、manhattan距离。

其实如果仅以测试集的测试结果来看,这个参数的选择并不是最好的,甚至算是中等。但是在自己找的数据上测试的结果要稍微好一些。

因为这个自己的数据因为并没有经过测试,并且风格上和数据集中的有非常大的差异,所以基本上正确的预测是很少出现的。有的参数基本上预测不对一个。而这个参数的选择会对几个。

所以来说这个参数的选择使得模型的泛化能力增强不少。而其他的都仅仅智能预测数据集中的结果。

数据集是mnist_784 。手写数字识别的数据集。总共有70000张照片,每个照片都是28*28个像素点,分为256个灰度级。总共分为1到9,10个类别。

测试集的话,除了数据集划分而来的,还有两部分。一是去找的数字照片把它们都转换成28*28的灰度二值图像。二是从数据集中找了几张照片,通过降低清晰度、模糊处理、残缺部分的方式处理得到的。

实验详细操作步骤或程序清单

from sklearn.datasets import fetch_openml
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import StandardScaler
from sklearn import metrics
from sklearn.metrics import recall_score, classification_report, precision_score, confusion_matrix
上边的是导入必要的包、库。


用于加载 MNIST 数据集和 获取特征和标签
mnist = fetch_openml(name="mnist_784", as_frame=True, parser='auto')
print(mnist)
X = mnist['data']
y = mnist['target']


print(X, '\n', y)   # 打印数据看一看


# 划分训练集和测试集
# X_train, X_test, y_train, y_test = train_test_split(mnist.data, mnist.target, test_size=0.2, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(mnist.data, mnist.target, test_size=0.2)

# 创建 StandardScaler 对象
scaler = StandardScaler()

# 对训练集进行标准化  原因是因为有不同的灰度级,所以标准化一下
X_train = scaler.fit_transform(X_train)

# 对测试集进行标准化  按照标准化训练集的方式标准化一下测试集
X_test = scaler.transform(X_test)

# 创建 KNN 分类器   下边的是使用过的参数,但是最后选择了没有注释的那一个。
# knn = KNeighborsClassifier(n_neighbors=5)
# knn = KNeighborsClassifier(n_neighbors=9, metric='manhattan', weights='distance')


# knn = KNeighborsClassifier(n_neighbors=7, metric='manhattan', weights='uniform') # 训练集可以,自己的一塌糊涂
# knn = KNeighborsClassifier(n_neighbors=5, metric='minkowski', weights='distance') # 测试数据都错几个,偏向3
# knn = KNeighborsClassifier(n_neighbors=1, metric='manhattan', weights='distance') # 3和7都很常见
# knn = KNeighborsClassifier(n_neighbors=5, metric='manhattan', weights='distance') # 更偏爱3
# knn = KNeighborsClassifier(n_neighbors=3, metric='manhattan', weights='distance') # 效果还行,训练集的测试不错,自己找的全是7
knn = KNeighborsClassifier(n_neighbors=9, metric='manhattan', weights='distance') # 效果稍微好些,在训练集里的测试不错,

# 在训练集上训练 KNN 模型
knn.fit(X_train, y_train)

# 在测试集上进行预测
y_pred = knn.predict(X_test)

# 在测试集上进行预测
y_pred = knn.predict(X_test)

accuracy = metrics.accuracy_score(y_test, y_pred)
print("准确率:", accuracy)

confusion_matrix = metrics.confusion_matrix(y_test, y_pred)
print("混淆矩阵:")
print(confusion_matrix)



# 查准率,预测为正类的样本中,真正为正类的样本所占的比例
print(precision_score(y_test, y_pred, average='micro'))

# 查全率, 真正为正类的样本中,被分类器预测为正类的样本所占的比例
print(recall_score(y_test, y_pred, average='micro'))

print(classification_report(y_test, y_pred, ))

准确率和混淆矩阵如下:
在这里插入图片描述
查准率、查全率和分类模型评估报告:
在这里插入图片描述

import matplotlib.pyplot as plt

# 假设您已经加载了MNIST数据集并将其存储在变量mnist中
# mnist = fetch_openml(name="mnist_784", as_frame=True, parser='auto')

# 显示前几张图片
for i in range(6,11):
    image = mnist.data.iloc[i].values.reshape(28, 28)  # 将图像数据转换为28x28的矩阵
    plt.subplot(6, 11, i + 1)
    plt.imshow(image, cmap='gray_r')
    plt.axis('off')

plt.show()

for i in range(12,20):
    image = mnist.data.iloc[i].values.reshape(28, 28)  # 将图像数据转换为28x28的矩阵
    plt.subplot(12, 20, i + 1)
    plt.imshow(image, cmap='gray_r')
    plt.axis('off')

plt.show()
# 上边的代码会输出这个数据集的一些照片,合理修改for循环里的数字能输出不同的数字,可以把输出的结果截屏一下,经过一些处理可以作为测试 ,不过因为截屏再加上处理,会失去许多的细节,所以预测的效果也是非常糟糕 。


# 下边的是用的自己找的数据,总体上效果非常不好,但是这个参数的选取会对几个
#  可以自己去找一些手写的照片,保存在"../data/"中,然后这下面的程序会转换成合适的数据然后测试。
# 但是需要自己把照片的名字改成从1到15。
# ==================================================================
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image

for i in range(15):
# 读取自己的照片并转换为灰度图像
image_path = "../data/" + str(i) + ".jpg"
image = Image.open(image_path).convert('L') # 转换为灰度图像

image = image.resize((28, 28)) # 调整大小为28x28像素
image_array = np.array(image) # 转换为数组

# 对图像数据进行标准化
image_data = image_array.reshape(1, -1)
image_data = scaler.transform(image_data)

# 显示照片内容
plt.imshow(image_array, cmap='gray')
plt.axis('off') # 关闭坐标轴
plt.show()

# 使用KNN模型进行预测
prediction = knn.predict(image_data)
# 输出预测结果
print("预测结果:", prediction)
#  ====================================================================

# 下边的是对数据集中的数据经过处理后的数据。因为数字主体经过平移、残缺、模糊处理,所以识别度也不是特别高。
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image

for i in range(13):
# 读取自己的照片并转换为灰度图像
image_path = "../hand_data/" + str(i) + ".jpg"
image = Image.open(image_path).convert('L') # 转换为灰度图像

image = image.resize((28, 28)) # 调整大小为28x28像素
image_array = np.array(image) # 转换为数组

# 对图像数据进行标准化
image_data = image_array.reshape(1, -1)
image_data = scaler.transform(image_data)

# 显示照片内容
plt.imshow(image_array, cmap='gray')
plt.axis('off') # 关闭坐标轴
plt.show()

# 使用KNN模型进行预测
prediction = knn.predict(image_data)
# 输出预测结果
print("预测结果:", prediction)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这就是自己处理后的照片的测试结果,感觉准确率不到0.2 …

相对来说,这个数据集的选取可能稍微有点不太适合,因为这种数字识别的数据集更应该跟深度学习结合起来,而是用k近邻算法的话,会更加的依靠训练集。简而言之,就是k近邻算法的泛化能力不是很强,毕竟作为一个懒惰的学习算法确实不能跟其他更高级的相比。因为我感觉这个模型之所以对我自己找的数据和处理原来数据集的数据来说,明显效果非常差,也就是说它并不能找到真正的特征,只是说用距离这种判断依据还是过于依赖测试集了。而且对风格的要求很多。对于手写的照片来说,如果训练集都是很工整的,测试集都很潦草就会效果很差,如果训练集都是笔画很细的,测试集笔画粗一些就会效果很差。

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

远歌已逝

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值