KNN算法及python实现

KNN算法原理和python实现

K最近邻(kNN,k-NearestNeighbor)分类算法是数据挖掘分类技术中最简单的方法之一。
原理是:如果一个样本在特征空间中的k个最相邻的样本中的大多数属于某一个类别,则该样本也属于这个类别,并具有这个类别上样本的特性。
在这里插入图片描述
绿色圆要被决定赋予哪个类,是红色三角形还是蓝色四方形?如果K=3,由于红色三角形所占比例为2/3,绿色圆将被赋予红色三角形那个类,如果K=5,由于蓝色四方形比例为3/5,因此绿色圆被赋予蓝色四方形类。
在这里插入图片描述
具体原理如下:在实际生活中不同的商品都有着不同的维度,如图,如果我们的样品想要知道在某个维度,利用欧几里得距离公式,可以获得他对所有点的距离,然后从小到大排列,给一个权重K,k的值是几,就取前几,前几中最多的属于哪个,它就属于哪个
代码实现:
knn算法需要自定义K值,需要传入训练数据,这个训练数据就是让机器学习的数据,训练数据是把文件读取变成一个数组,多个文件相互堆叠行,就变成了矩阵。我们还需要测试数据,测试数据是一个单行矩阵。用它去跟所有的训练数据求距离。然后需要一个标签数组,标签标示他是属于哪一类.
KNN算法实现

  1. 导包
from sklearn import datasets  
#导入内置数据集模块                      
#导入sklearn.neighbors模块中KNN类
import numpy as np 
#导入KNN算法模块
from sklearn.neighbors import KNeighborsClassifier
#数据分类
from sklearn.model_selection import train_test_split
#归一化处理
from sklearn.preprocessing import MinMaxScaler
#混淆矩阵包
from sklearn.metrics import confusion_matrix,recall_score,classification_report,accuracy_score
#导入 精度值计算包,得自己下载,在sklearn最后里面
import pandas  as pd
import matplotlib.pyplot as plt
import seaborn  as sns
  1. 先拿鸢尾花的训练集做一个例子
iris=datasets.load_iris()
iris_x=iris.data 
#导入数据,数据是个矩阵
#knn算法中x是数据,是一个二维数组,横着的是数据个数,列表示数据的东西
y = iris.target
scaler = MinMaxScaler()#导入归一化库,归一化有两种方法min-max标准化(Min-Max Normalization)和Z-score标准化方法
x = scaler.fit_transform(iris_x)
 #归一化的作用是把结果映射到0到1之间,目的是跟标准化一样的
 train_X,test_X, train_y, test_y = train_test_split(iris_x,  y, test_size=0.2)
 #创建训练数据和测试数据
 # KNN模型,选择3个邻居
model = KNeighborsClassifier(n_neighbors=3)
model.fit(train_X, train_y)#建立模型
y_pred = model.predict(test_X)

cnf_matrix =confusion_matrix(test_y,y_pred)
#把小数位数改为2位
np.set_printoptions(precision=2)
#输出模型精度,这个可没有逻辑回归的recall
print(accuracy_score(test_y,y_pred))
#混淆矩阵的含义,我们有三个分类,所以值也为3*3,0行是真实值,预测成0的9个,预测成1的0个,预测成2的0个。
#原本真实值是1,第二行,预测成0的为0个,预测成1的为一个,预测成2的为0个,全部正确
#第三个就成问题了,原本是2,预测成0的0个,预测是1的1个,这个是错的,预测成2的7个,一共30个预测成功了29个,模型评估率96.67%
cnf_matrix
  1. 数据结果如下
0.966666666667
array([[ 9,  0,  0],
       [ 0, 13,  0],
       [ 0,  1,  7]], dtype=int64)

knn算法实现手写体识别
原理是把图片的像素点变成矩阵,不同颜色的值不一样,然后训练数据是好多个一维矩阵组成的二维矩阵,我们的数据是一个一维矩阵也可能是好多行,每一行减去所有训练数据,然后求欧拉距离,选取最近的几个距离是啥,就属于这一个类
图像处理:目的是把图像转换成0和1的矩阵文件

from PIL import Image#pillow这个包是为了对图片进行处理,使其变成0和1的矩阵
im = Image.open("D:/pyProject/knn/timg2.gif",mode ="r")
width = im.size[0]
height= im.size[1]
print(width)
ftwo = open("D:/pyProject/knn/timg2.txt","a")

for w in range(0,width):
for h in range(0,height):
#切记这个方法,如果是256色的图片返回值是int,如果是rgb返回的是元祖
col = im.getpixel((w,h))

if col == 0:
ftwo.write("1")
else:
ftwo.write("0")
print("\n")
ftwo.close()
#原理是把图像中的某个像素点的颜色计算出来,如果他是黑色就文档中写入1,不然写入0
import os
#读取数据
trains =  os.listdir("D:/pyProject/knn/digits/digits/trainingDigits")
#建立y数据的列表
yTrain=[]
path="D:/pyProject/knn/digits/digits/trainingDigits"
#建立x矩阵
x_juzhen=[]
for file in trains:
    xNum=[]
    for line in open(path+"/"+file).readlines():
        for num in line:
            if num != '\n':
               xNum.append(num) 
    num = file.split("_")[0]
    yTrain.append(num)
    x_juzhen.append(xNum)
#读取训练数据文件,将其转换成矩阵
yTrain = np.array(yTrain)
x_juzhen = np.array(x_juzhen)

#先建立模型,拿训练数据评估下模型看看
x_train,x_test,y_train,y_test = train_test_split(x_juzhen,yTrain,test_size=0.2)
model = KNeighborsClassifier(n_neighbors=5)
model.fit(x_train,y_train)#建立模型
y_pred = model.predict(x_test)

cnf_matrix =confusion_matrix(y_test,y_pred)
print(accuracy_score(y_test,y_pred))
cnf_matrix
#模型评估率为98%

结果如下:

0.984496124031
array([[40,  0,  0,  0,  0,  0,  0,  0,  0,  0],
       [ 0, 39,  0,  0,  0,  0,  0,  0,  0,  0],
       [ 0,  0, 45,  0,  0,  0,  0,  0,  0,  0],
       [ 0,  0,  0, 51,  0,  0,  0,  0,  0,  0],
       [ 0,  1,  0,  0, 38,  0,  0,  0,  0,  0],
       [ 0,  0,  0,  0,  0, 33,  0,  0,  0,  1],
       [ 0,  0,  0,  0,  0,  0, 37,  0,  0,  0],
       [ 0,  0,  0,  0,  0,  0,  0, 29,  0,  0],
       [ 0,  2,  0,  0,  0,  0,  0,  0, 29,  0],
       [ 0,  1,  0,  0,  1,  0,  0,  0,  0, 40]], dtype=int64)

然后我们随便拿一个手写数字去识别

cnf_matrix.sum()
387
#387个数字,只预测错了6个,下面我们拿一个测试数据看看
path2="D:/pyProject/knn/digits/digits/trainingDigits/7_14.txt"
test5=[]
for line in open(path2).readlines():
    for num in line:
        if num != '\n':
            test5.append(num)
test5=[test5]
test5 = np.array(test5)
y_pred = model.predict(test5)
y_pred

这个文件的内容如下:手写的一个数字7

00000000000000011111111110000000
00000000000001111111111110000000
00000000000001111111111110000000
00000000000111111111111110000000
00000000001111111111111110000000
00000000011111111111111100000000
00000000001111000000111110000000
00000000000100000000111110000000
00000000000000000001111100000000
00000000000000000000111100000000
00000000000000000001111000000000
00000000000000000001111000000000
00000000000000000001111000000000
00000000000000000011110000000000
00000000000000000011110000000000
00000000000000000111100000000000
00000000000000001111111111000000
00000000000001111111111111100000
00000000011111111111111111000000
00000000111111111111111110000000
00000011111111111110000000000000
00000111111111111110000000000000
00000111111110011110000000000000
00000111100000111100000000000000
00000000000000111110000000000000
00000000000000111100000000000000
00000000000000111100000000000000
00000000000000111100000000000000
00000000000001111000000000000000
00000000000001111000000000000000
00000000000011110000000000000000
00000000000011110000000000000000

输出结果:

array(['7'],
      dtype='<U1')

放进去一个7的文件,能够很好地识别

猜你喜欢

转载自blog.csdn.net/qq_41302130/article/details/82857693
今日推荐