KNN算法

K近邻法(k-nearst neighbors,KNN)是一种很基本的机器学习方法。它的思想是: 在训练集中数据和标签已知的情况下,输入测试数据,将测试数据的特征与训练集中对应的特征进行相互比较,找到训练集中与之最为相似的前K个数据,则该测试数据对应的类别就是K个数据中出现次数最多的那个分类。
kNN算法三要素
k值的选取,距离度量的方式和分类决策规则
KNN算法的步骤:
1、收集数据集
2、创建测试集和训练集
3、计算测试数据与各个训练数据之间的距离;
4、按照距离的递增关系进行排序;
5、选取距离最小的K个点;
6、评估算法的准确度
KNN算法的具体实现代码:

import numpy as np
import operator
from scipy.spatial import distance
from sklearn.datasets import load_iris
iris=load_iris()
#收集50组鸢尾花的数据
x_data = iris['data'][0:150]
#鸢尾花的类别(标签)
y_data = iris['target'][0:150]
#产生训练集
x_train = x_data[0:150:2]
y_train = y_data[0:150:2]
#产生测试集
x_test = x_data[1:150:2]
y_test = y_data[1:150:2]
class MyCreateKNN():
    #自己写的fit函数有两个参数,分别是训练集的特征和标签
    def fit(self,X_train,y_train,k):
        self.X_train=x_train
        self.y_train=y_train
        self.k=k
    #predict函数的返回值是预测的结果
    def predict(self,X_test):
        predictions=[]
        for row in X_test:
            #label=random.choice(self.y_train)
            label=self.closest_k(row)
            predictions.append(label)
        return predictions
    #closest函数就是找到离输入的数据点最近的一个点
    def closest_k(self,row):
        #distances存储测试点到数据集各个点的距离
        distances=[]
        for i in range(len(x_train)):
            dist=self.euc(row,self.X_train[i])
            distances.append(dist)
        #转换为数组,对距离排序(从小到大),返回位置信息
        distances=np.array(distances)
        sortedDistIndicies=distances.argsort()
        classCount={}
        for i in range(self.k):
            voteIlabel=y_train[sortedDistIndicies[i]]
            #次处get,原字典由此voteIlabel则返回其对应的值,没有则返回0
            classCount[voteIlabel]=classCount.get(voteIlabel,0)+1
        #根据值(对应“票数”)进行排序,使得获得票数多的类在前(故使用reverse=True)
        sortedClassCount=sorted(classCount.items(),
          										  key=operator.itemgetter(1),reverse=True)
        #返回改测试点的类型
        return sortedClassCount[0][0]
    #计算欧式距离
    def euc(self,a,b):
        return distance.euclidean(a,b)
from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test=train_test_split(x_data,y_data)
my_classifier=MyCreateKNN()
my_classifier.fit(x_train,y_train,k=3)
predictions=my_classifier.predict(x_test)
from sklearn.metrics import accuracy_score
print("测试准确率: ",accuracy_score(y_test,predictions))

实现的具体函数
1)实现fit函数,fit函数接受三个参数,分别是训练集的特征和标签,和k值(k为离测试值的最近的几个点)
2) 实现predict函数,建立一个列表predictions 来存放所有的类别结果,遍历每一个测试集里面的特征值数据,并选取距离最近的点(根据k值的不同)的类别作为判别的结果,并将其加入predictions中。
3)算距离:实现closest函数 找到离输入的数据点最近的一个点,并将此最近点的类别作为该点类别的预测值返回。首先将测试点与训练集第一个数据点的距离设为初始最小距离,并将第一个点设为初始最临近的点。之后遍历训练集的每一个点,只要距离比之前的点小,就更新最短距离。并更新其所属类别(通过记录索引值来记录其类别)。在遍历完训练集所有的点之后,此时的best_dist是最小的,其对应的类别就是y_train[best_index],最后通过距离函数(欧氏距离)euc计算数据点之间的距离。
画出散点矩阵图
参考的链接为:

画出散点图的源代码为:

import matplotlib.pyplot as plt
# 山鸢尾花的数据
iris_setosa = x_data[0:50]  
 # 变色鸢尾花花的数据
iris_versicolor = x_data[50:100]  
 # 维吉尼亚鸢尾花的数据
iris_virginica = x_data[100:150]  
# 运用numpy.hsplit水平分割获取各特征集合,分割成四列
iris_setosa = np.hsplit(iris_setosa, 4)  
iris_versicolor = np.hsplit(iris_versicolor, 4)
iris_virginica = np.hsplit(iris_virginica, 4)
 
setosa = {'sepal_length': iris_setosa[0], 'sepal_width': iris_setosa[1], 'petal_length': iris_setosa[2],
          'petal_width': iris_setosa[3]}
 
versicolor = {'sepal_length': iris_versicolor[0], 'sepal_width': iris_versicolor[1], 'petal_length': iris_versicolor[2],
              'petal_width': iris_versicolor[3]}
 
virginica = {'sepal_length': iris_virginica[0], 'sepal_width': iris_virginica[1], 'petal_length': iris_virginica[2],
             'petal_width': iris_virginica[3]}
# 散点的大小
size = 5 
#蓝色代表山鸢尾花
setosa_color = 'b'  
#绿色代表变色鸢尾花
versicolor_color = 'g'  
#红色代表维吉尼亚鸢尾花
virginica_color = 'r'  
sepal_width_ticks = np.arange(2, 5, step=0.5)  # sepal_length分度值和刻度范围
sepal_length_ticks = np.arange(4, 8, step=0.5)  # sepal_width分度值和刻度范围
petal_width_ticks = np.arange(0, 2.5, step=0.5)  # petal_width分度值和刻度范围
petal_length_ticks = np.arange(1, 7, step=1)  # petal_length分度值和刻度范围
ticks = [sepal_length_ticks, sepal_width_ticks, petal_length_ticks, petal_width_ticks]
label_text = ['Sepal.Length', 'Sepal.Width', 'Petal.Length', 'Petal.Width']
plt.figure(figsize=(12, 12))  # 设置画布大小
plt.suptitle("Iris Set (blue=setosa, green=versicolour, red=virginca) ", fontsize=30)

for i in range(0, 4):
    for j in range(0, 4):
        plt.subplot(4, 4, i * 4 + j + 1) # 创建子画布
        if i == j:
            plt.xticks([])
            plt.yticks([])
            plt.text(0.1, 0.4, label_text[i], size=18)
        else:
            plt.scatter(iris_setosa[j], iris_setosa[i], c=setosa_color, s=size)
            plt.scatter(iris_versicolor[j], iris_versicolor[i], c=versicolor_color, s=size)
            plt.scatter(iris_virginica[j], iris_virginica[i], c=virginica_color, s=size)
            # plt.xlabel(label_text[j])
            # plt.ylabel(label_text[i])
            plt.xticks(ticks[j])
            plt.yticks(ticks[i])
plt.show()

运行结果为:

python中对knn模型调参parms python中knn算法_python