当前位置:   article > 正文

K-近邻算法_knn分类器利用kneighborsclassifier函数制作knn分类器

knn分类器利用kneighborsclassifier函数制作knn分类器

目录

1.k-近邻算法概述

1.1准备:使用Python导入数据

1.2从文本文件中解析数据

2.实例:使用K-近邻算法实现猫狗分类

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

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

2.3效果图展示

3.常见错误及解决思路

1.k-近邻算法概述

KNN(K-Nearest Neighbor)算法是机器学习算法中最基础、最简单的算法之一。它既能用于分类,也能用于回归。KNN通过测量不同特征值之间的距离来进行分类。KNN算法的核心思想是:在已知训练集数据及其标签的情况下,对于一个新输入的测试数据,算法会在训练集中找到与这个测试数据最相似的K个邻居,然后根据这K个邻居的类别来决定测试数据的类别。

具体来说,算法的步骤包括:

  1. 计算距离:计算测试数据与训练集中每个数据点之间的距离。
  2. 选择邻居:按照距离大小对训练数据进行排序,选择距离最小的K个数据点作为邻居。
  3. 投票决策:统计这K个邻居中各个类别的出现频率,频率最高的类别即为测试数据的预测分类。

此过程中我们计算距离需要运用到欧式距离公式,计算两个向量点xA和xB之间的距离:d=\sqrt{(xA0-xB0)^{2}+(xA1-xB1)^{2}}

亦或者,也可以采用曼哈顿距离:

d = \left | x1-x2 \right |+\left | y1-y2 \right |

而后,我们通过选定的k值。将输入的数据通过计算与其它点之间的距离按从小到大排序,选定k个值,计算这k个值里面各类别出现的频率,将频率最高的类别复制给输入的数据作为其标签。

该算法的优点为:

        (1)简单易用;

        (2)模型训练时间快(惰性模型,不需要对数据作出任何的假设,完全根据数据决定);

        (3)预测效果好;

        (4)对异常值不敏感。

该算法的缺点为:

        (1)计算量较大,预测阶段可能较慢;

        (2)对内存要求高,该算法存储了所有训练数据;

        (3)对不相关的功能和数据规模敏感。

1.1准备:使用Python导入数据

首先我们需要去寻找数据集,并将数据集下载到本地。常见的免费数据集下载地址有:https://www.kaggle.com/datasets

https://tianchi.aliyun.com

本次实验我是从kaggle中下载了猫狗的数据集,其数据集中准备了测试集、训练集、验证集的图片文件夹,以及文本(文本中存放了图片的数据和标签)。

在进行导入数据前,我们需要导入一些必要的库,以用来后面进行数据的处理。(这仅是部分,若有需要可以按自己的代码补充相对应的库)

  1. import os
  2. import cv2
  3. import numpy as np
  4. from sklearn.model_selection import train_test_split
  5. from sklearn.neighbors import KNeighborsClassifier
  6. from sklearn.metrics import accuracy_score
  7. from PIL import Image
  8. import matplotlib.pyplot as plt

导入数据我们一般可以采用open、readlines函数来实现,亦或者可以采用pandas库中的pd.read_csv来实现(若数据集为csv文件)

  1. fr = open(filename)
  2. arrayOLines = fr.readlines()
  3. numberOfLines = len(arrayOLines)

ps:filename是自己的数据集路径

1.2从文本文件中解析数据

首先我们需要从txt文本中,将数据进行导入和分割,因为该文本中的数据是分为两列属性。我们可以采用img,classLabelVector来分别存储。

  1. def file2matrix(filename):
  2. fr = open(filename)
  3. arrayOLines = fr.readlines()
  4. numberOfLines = len(arrayOLines)
  5. classLabelVector = []#用于存放标签
  6. img = []#用于存放图片
  7. index = 0
  8. for line in arrayOLines:
  9. line = line.strip()
  10. listFromLine = line.split('\t')#将数据集每一行都分割来 分割后为'cats/cat.4987.jpg 0'
  11. for item in listFromLine:
  12. img_path, classLabel = item.split(' ')
  13. img_data = image_to_feature_matrix(img_path)
  14. img.append(img_data)
  15. classLabelVector.append(int(classLabel))
  16. index += 1
  17. return classLabelVector, img

(1)代码思路:我们首先通过Open函数打开存放有我们数据和标签的文件,通过readlines遍历文本当中的每一行。img,classLabelVector分别用来存放图片数据和标签。此后通过一次for循环,将文本数据中的每一行通过换行符进行分割,而后分割后的每一行数据在进行for循环,通过空格符进行分割,并通过append函数,存储在相对应的数组中。

如果你想要实现图像识别分类,你需要将图片信息转化为灰度图,而后将灰度图转换为特征向量来进行存储,否则很容易会造成输入的规模与分类器的规模不一致的问题。(因为我下载的数据集txt文本中图片不是完整路径,因此这里采用了拼接路径)

  1. def image_to_feature_matrix(image_path, size=(64, 64)):
  2. # 读取图片文件
  3. img = cv2.imread('C:\\AI\\Lib\\cats_dogs_dataset\\'+image_path)
  4. # 缩放图片
  5. img = cv2.resize(img, size)
  6. # 将图片转换为灰度图
  7. gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  8. # 将灰度图转换为特征向量
  9. feature_vector = gray_img.flatten()
  10. return feature_vector

2.实例:使用K-近邻算法实现猫狗分类

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

我们通过for循环和split分割属性,将其分别加入到对应的数组中,我们需要对图像进行处理(为了保证输入规模与KNN分类器的规模一致)。我们需要将图片转化为灰度图,并将其转化为特征向量存储。

  1. def image_to_feature_matrix(image_path, size=(64, 64)):
  2. # 读取图片文件
  3. img = cv2.imread('C:\\AI\\Lib\\cats_dogs_dataset\\'+image_path)
  4. # 缩放图片
  5. img = cv2.resize(img, size)
  6. # 将图片转换为灰度图
  7. gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  8. # 将灰度图转换为特征向量
  9. feature_vector = gray_img.flatten()
  10. return feature_vector
  11. def file2matrix(filename):
  12. fr = open(filename)
  13. arrayOLines = fr.readlines()
  14. numberOfLines = len(arrayOLines)
  15. classLabelVector = []#用于存放标签
  16. img = []#用于存放图片
  17. index = 0
  18. for line in arrayOLines:
  19. line = line.strip()
  20. listFromLine = line.split('\t')#将数据集每一行都分割来 分割后为'cats/cat.4987.jpg 0'
  21. for item in listFromLine:
  22. img_path, classLabel = item.split(' ')
  23. img_data = image_to_feature_matrix(img_path)
  24. img.append(img_data)
  25. classLabelVector.append(int(classLabel))
  26. index += 1
  27. return classLabelVector, img

而后,我们采用KNN算法,定义一个classify函数,其中inX为输入的向量,X_train为训练集,labels为标签,k为选定的值。我们可以通过采用欧式距离公式来进行计算,而后通过最近距离的k个点频率最高的类别来确定输入数据的标签。

  1. def classify(inX, X_train, labels, k):#knn算法
  2. dataSetSize = len(X_train)
  3. diffMat = np.tile(inX, (dataSetSize, 1)) - X_train
  4. sqDiffMat = diffMat**2
  5. sqDistance = sqDiffMat.sum(axis=1)
  6. distances = sqDistance**0.5
  7. sortedDisIndicies = distances.argsort()
  8. classCount = {}
  9. for i in range(k):
  10. voteIlabel = labels[sortedDisIndicies[i]]
  11. classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
  12. sortedClassCount = sorted(classCount.items(), key=lambda x: x[1], reverse=True)
  13. return sortedClassCount[0][0]

而后我们可以通过train_test_split函数来划分训练集和测试集,在该示例中,我们将测试集设置为百分之二十。然后将img,classLabelVector分别作为训练集和测试集的参数传入。

  1. if __name__ == "__main__":
  2. filename = 'C:\\AI\\Lib\\cats_dogs_dataset\\test.txt'
  3. classLabelVector, img = file2matrix(filename)
  4. print(img)
  5. print(classLabelVector)
  6. # 划分训练集和测试集
  7. X_train, X_test, y_train, y_test = train_test_split(img, classLabelVector, test_size=0.2, random_state=42)

进一步地,我们可以通过KNeighborsClassifier函数创建KNN分类器,也可以自主设置img_path,并通过我们定义的classify函数来实现knn算法及预测。

  1. # 创建KNN分类器
  2. knn = KNeighborsClassifier(n_neighbors=3)
  3. #通过输入预测
  4. img_path = 'cats/cat.4358.jpg'
  5. inX = image_to_feature_matrix(img_path)
  6. knn1 = classify(inX, X_train, y_train, k=3)
  7. print(knn1)

接下来就是训练模型以及计算该模型的准确率。我们可以通过fit、predict、accuracy_score函数来实现该功能。

  1. # 训练模型
  2. knn.fit(X_train, y_train)
  3. # 预测
  4. y_pred = knn.predict(X_test)
  5. # 计算准确率
  6. accuracy = accuracy_score(y_test, y_pred)
  7. print("准确率:", accuracy)

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

创建散点图之前,我们需要导入plt库(用来制图)。我们可以利用plt库当中的xlabel、ylabel来设置横纵坐标,scatter则可以用来绘制点的分散,我们可以设置点的颜色,以及某个颜色所代表的意义。最后我们通过show函数来展示散点图的分布。

  1. #散点图分布
  2. plt.scatter(range(len(y_pred)), y_pred, c='r', label='Predicted')
  3. plt.scatter(range(len(y_test)), y_test, c='b', label='True')
  4. plt.xlabel('Index')
  5. plt.ylabel('Class')
  6. plt.legend()
  7. plt.show()

2.3效果图展示

该结果展示的是特征矩阵,因为该示例的数据集为猫狗图片,因此特征矩阵存放的是像素的值。

该结果展示的是各图片所对应的标签,其中0表示猫,1表示狗。

该图片展示的是散点图的分布,因为该示例为二分类任务。从该图上看来,该模型的性能还是较好的。

3.常见错误及解决思路

常见错误:(1)我们在对图像数据进行存储的时候,规模和分类器的规模会不一致。

                  (2)在进行数据分割的时候,很容易造成分割不完全,以至于后续无法找到正确路径

                  (3)找不到txt文件中的图片文件出现FileNotFound的Error

解决思路:(1)我们利用cv2进行图像的转化,将其像素的值存储到img数组中,当中可以利用flatten来将其拉伸为一维数组

                  (2)我们在分割的时候需要注意我们每一步代码,分割后的结果是什么,像该示例我们第一次按换行符进行分割,分割的结果是文本内的每一行数据。需要在进行一次分割,将图像数据与标签分别进行存储

                  (3)因为txt文件当中的图像数据并不是完整的路径,因此我们需要通过拼接路径,将完整的图片路径拼出来。

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号