分类算法KNN的python实现
创始人
2024-05-02 12:14:54
0

作者:刘凡

KNN算法介绍

KNN算法是有监督学习中的分类算法,它是一种非参的,惰性的算法模型。非参的意思并不是说这个算法不需要参数,而是意味着这个模型不会对数据做出任何的假设,与之相对的是线性回归(我们总会假设线性回归是一条直线)。也就是说KNN建立的模型结构是根据数据来决定的,这也比较符合现实的情况,毕竟在现实中的情况往往与理论上的假设是不相符的。惰性的意思是指模型在使用前不会被训练,只有当使用的时候才会被训练。

KNN算法优点: 简单易用,相比其他算法,KNN算是比较简洁明了的算法。即使没有很高的数学基础也能搞清楚它的原理。可以处理多分类问题;还可以处理回归问题。

KNN算法缺点: 对内存要求较高,因为该算法存储了所有训练数据,预测阶段可能很慢;对训练数据依赖度特别大,虽然所有机器学习的算法对数据的依赖度很高,但是KNN尤其严重,因为如果我们的训练数据集中,有一两个数据是错误的,刚刚好又在我们需要分类的数值的旁边,这样就会直接导致预测的数据的不准确,对训练数据的容错性太差;维数灾难。

自编函数实现

#欧氏距离
def distance(a,b):return np.sqrt(np.sum((a-b)**2,axis=1))
# 分类器实现
class kNN(object):# 定义初始化方法,初始化kNN需要的参数def __init__(self,n_neighbors = 1,dist_func = distance):self.n_neighbors = n_neighborsself.dist_func = dist_func# 训练模型方法def fit(self,x,y):# 将x,y传进来即可self.x = xself.y = y# 模型预测方法def predict(self,x):# 初始化预测分类数组y_pred = np.zeros((x.shape[0],1),dtype = self.y.dtype)# 遍历输入的x数据点,取出每一个数据点的i和数据x_testfor i,x_test in enumerate(x):# x_test跟所有的训练数据计算距离distances = self.dist_func(self.x,x_test)# 得到的距离按照由近到远排序nn_index = np.argsort(distances)# 选取最近的k个点,保存其类别nn_y = self.y[nn_index[:self.n_neighbors]].ravel()# 统计类别中频率最高的那个,赋给y_pred[i]y_pred[i] = np.argmax(np.bincount(nn_y))return y_pred   

测试

import numpy as np 
import pandas as pd
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_scoreiris = load_iris()
# 划分训练集和测试集
x = iris.data
y = iris.target.reshape(-1,1)#将iris.target 行向量,转换成列
x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.3)knn = kNN(n_neighbors = 3)
knn.fit(x_train,y_train)
# 传入测试数据,做预测
y_pred = knn.predict(x_test)# 求准确率
accuracy = accuracy_score(y_test,y_pred)
print('预测准确率:',accuracy)
'''预测准确率: 0.9777777777777777'''

调参

knn = kNN()
# 训练模型
knn.fit(x_train,y_train)# 创建一个列表保存不同的准确率
result_list = []
knn.dist_func = distance# 考虑不同的k值
for k in range(1,10,1):knn.n_neighbors = k# 传入测试数据,做预测y_pred = knn.predict(x_test)# 求出预测准确率accuracy = accuracy_score(y_test,y_pred)result_list.append([k,accuracy])df  = pd.DataFrame(result_list,columns = ['k','预测准确率'])
df 

在这里插入图片描述

sklearn模块的实现

参数介绍

sklearn.neighbors 模块中的KNeighborsClassifier类可以实现KNN算法。

KNeighborsClassifier(n_neighbors=5, *, weights='uniform', algorithm='auto', leaf_size=30, p=2, metric='minkowski', metric_params=None, n_jobs=None)
  • n_neighbors: int, 可选参数(默认为 5)用于kneighbors查询的默认邻居的数量

  • weights(权重): str or callable(自定义类型), 可选参数(默认为 ‘uniform’)用于预测的权重函数。可选参数如下:

    • ‘uniform’ : 统一的权重. 在每一个邻居区域里的点的权重都是一样的。
    • ‘distance’ : 权重点等于他们距离的倒数。使用此函数,更近的邻居对于所预测的点的影响更大。
    • ‘callable’ : 一个用户自定义的方法,此方法接收一个距离的数组,然后返回一个相同形状并且包含权重的数组。
  • algorithm(算法): {‘auto’, ‘ball_tree’, ‘kd_tree’, ‘brute’}, 可选参数(默认为 ‘auto’)
    计算最近邻居用的算法:

    • ‘ball_tree’是为了克服kd树高纬失效而发明的,其构造过程是以质心C和半径r分割样本空间,每个节点是一个超球体。 ball-tree按超球面进行划分。球树:找到一个中心点,使所有样本点到这个中心点的距离最短。对于每一个节点的子节点的选择,方式如下:选择当前超球体区域离中心最远的点作为左子节点选择距离左子节点距离最远的点作为右子节点对于其他的样本点,计算到左子节点和右子节点对应样本点的欧式距离,并分配到距离较近的那一个对所有子节点做相同的操作
    • ‘kd_tree’ 构造kd树存储数据以便对其进行快速检索的树形数据结构,kd树也就是数据结构中的二叉树。以中值切分构造的树,每个结点是一个超矩形,在维数小于20时效率高。
    • Kd-tree按维度逐次划分kd 树是一个二叉树,每一个内部的节点都代表了一个超矩形空间,并且它的子树包含在这个超矩形空间内部的所有样本点。但是 kd 树对于一些样本分布情况而言效率并不高,比如当大量样本落在一个超矩形的角落的情况,此时使用球树的效率会更高
    • ‘brute’ 使用暴力搜索.也就是线性扫描,当训练集很大时,计算非常耗时
    • ‘auto’ 会基于传入fit方法的内容,选择最合适的算法。
  • leaf_size(叶子数量): int, 可选参数(默认为 30)。传入BallTree或者KDTree算法的叶子数量。此参数会影响构建、查询BallTree或者KDTree的速度,以及存储BallTree或者KDTree所需要的内存大小。 此可选参数根据是否是问题所需选择性使用

  • p: integer, 可选参数(默认为 2)。 用于Minkowski metric(闵可夫斯基空间)的超参数。p = 1, 相当于使用曼哈顿距离 (l1),p = 2, 相当于使用欧几里得距离(l2) 对于任何 p ,使用的是闵可夫斯基空间(l_p)

  • metric(矩阵): string or callable, 默认为 ‘minkowski’用于树的距离矩阵。默认为闵可夫斯基空间,如果和p=2一块使用相当于使用标准欧几里得矩阵. 所有可用的矩阵列表请查询 DistanceMetric 的文档。

  • metric_params(矩阵参数): dict, 可选参数(默认为 None)给矩阵方法使用的其他的关键词参数。

  • n_jobs: int, 可选参数(默认为 1), 用于搜索邻居的,可并行运行的任务数量。设定工作的core数量,如果为-1, 任务数量设置为CPU核的数量。不会影响fit方法。

测试

#测试
import numpy as np 
import pandas as pd
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.neighbors import KNeighborsClassifieriris = load_iris()
# 划分训练集和测试集
x = iris.data
y = iris.target.reshape(-1,1)#将iris.target 行向量,转换成列
x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.3)knn = KNeighborsClassifier(n_neighbors=3,weights='uniform',algorithm='auto')knn.fit(x_train,y_train)
# 传入测试数据,做预测
y_pred = knn.predict(x_test)# 求准确率
accuracy = accuracy_score(y_test,y_pred)
print('预测准确率:',accuracy)
'''预测准确率: 0.9555555555555556'''

计算混淆矩阵

sklearn.metrics模块中的confusion_matrix和classification_report 函数可以计算出混淆矩阵和预测正确率等指标。

from sklearn.metrics import confusion_matrix,classification_report 
print(confusion_matrix(y_test, y_pre))
print(classification_report(y_test, y_pre))

在这里插入图片描述

相关内容

热门资讯

除夕的作文700字 精选除夕的作文700字十篇  在日常生活或是工作学习中,大家一定都接触过作文吧,作文是人们把记忆中所...
文具盒的自述作文 文具盒的自述作文(5篇)  在平时的学习、工作或生活中,大家总少不了接触作文吧,作文是一种言语活动,...
元旦晚会作文800字 【精选】元旦晚会作文800字3篇  在日常的学习、工作、生活中,大家都接触过作文吧,作文是由文字组成...
眼光的作文 关于眼光的作文  在平日的学习、工作和生活里,大家都经常看到作文的身影吧,借助作文人们可以反映客观事...
一次难忘的经历作文 一次难忘的经历作文800字(通用24篇)  无论在学习、工作或是生活中,大家最不陌生的就是作文了吧,...
家乡的小河作文 家乡的小河作文400字(精选112篇)  家乡这座美丽的古城见证了海上丝绸之路的兴衰,经历了无尽的风...
气球大爆炸作文 气球大爆炸作文7篇  篇一:玩气球大爆炸游戏  7月27日 星期六 晴今天,我们在水木青华作文室举行...
我的一次科学尝试作文 我的一次科学尝试作文大全  【篇一:我的一次科学尝试】  有一次,我正在拿着凹的乒乓球看,愁眉苦脸,...
秋韵秋味作文650字 秋韵秋味作文650字  在学习、工作、生活中,大家都接触过作文吧,借助作文可以提高我们的语言组织能力...
让悲剧停止 让悲剧停止让悲剧停止  罗布泊,“泊”字左边是三点水啊!曾经的它是一个牛马成群、绿林环绕、水如明镜的...
园丁颂作文1100字 园丁颂作文1100字  老师,大家都说您培养着祖国的栋梁;我却要说,您就是祖国的栋梁。正是您,支撑起...
让我感动的祖狄作文400字 让我感动的祖狄作文400字  祖狄是晋代的一个心胸宽广、有远大理想的人。他小时候是一个不爱读书的人,...
我感恩我作文900字 【精选】我感恩我作文900字4篇  在学习、工作或生活中,大家都不可避免地要接触到作文吧,作文是一种...
描写麻雀的作文 描写麻雀的作文(通用43篇)  麻雀,一种频繁的动物。无论在城市,乡村,甚至电线杆上,都随处可见。他...
告诉你一件尴尬的事作文800... 告诉你一件尴尬的事作文800字(精选67篇)  要想写好作文,优秀的题材是少不了的,所以平常要多少读...
啄木鸟作文 啄木鸟作文啄木鸟一天,天气晴朗,森林里召开大会。有人说:“最近,有一棵千年老树身体里有了一些害虫,我...
你还好吗作文 你还好吗作文800字(通用25篇)  在我们平凡的日常里,大家总免不了要接触或使用作文吧,借助作文人...
我爱祖国作文 我爱祖国作文1000字(通用17篇)  无论是在学校还是在社会中,大家都不可避免地会接触到作文吧,写...
多彩活泼的秋天作文 多彩活泼的秋天作文  在日常学习、工作和生活中,大家对作文都不陌生吧,借助作文可以提高我们的语言组织...
火龙果作文450字 火龙果作文450字(精选10篇)  在平日的学习、工作和生活里,大家都经常接触到作文吧,借助作文人们...