【python】KNN(K近邻算法)实现及可视化

【python】KNN(K近邻算法)实现及可视化
⽂章⽬录
KNN(K近邻算法)实现及可视化
1 算法描述:
KNN的⼯作原理::给定⼀个已知标签类别的训练数据集,输⼊没有标签的新数据后,在训练数据集中到与新数据最邻 近的k个实例,如果这k个实例的多数属于某个类别,那么新数据就属于这个类别。可以简单理解为:由那些离X最 近的k个点来投票决定X归为哪⼀类。
它的算法步骤为:(1) 计算已知类别数据集中的点与当前点之间的距离; (2) 按照距离递增次序排序; (3) 选取与当前点距离最⼩的k个点; (4) 确定前k个点所在类别的出现频率; (5) 返回前k个点出现频率最⾼的类别作为当前点的预测类别。
2 KNN算法的Python实现:
2.1 实践问题背景:
现要将⽬标分为四类,分别记为第0类、第1类、第2类、第3类。
2.2 ⽬标:
给定⽬标向量,得出其所属类别。
⽬标数据集是⼀个15⾏,每⾏有两个特征值的数据集。詹姆斯 罗伯特
2.3 数据集:
[外链图⽚转存失败,源站可能有防盗链机制,建议将图⽚保存下来直接上传(img-tsQIaCgx-1609429162595)
(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201126101025891.png)]
数据集从上⾄下依次代表了第0类到第3类数据。每个数据集有50⾏数据,每⾏有两个特征值。
2.4 要求:
通过python实现k最近邻算法。
2.5 实施步骤:
① 准备数据:
# loadtxt()函数是读取txt ⽂件,注意被读取的⽂件需要数据⽂件要求每⼀⾏数据的格式相同
data1 = np.loadtxt('')
#绘制散点图
#scatter中的参数,第⼀个为横轴值,第⼆个为纵轴值,第三个为点的颜⾊
plt.scatter(data1[:,0],data1[:,1],color="r")
data2 = np.loadtxt('')
plt.scatter(data2[:,0],data2[:,1],color="g")
data3 = np.loadtxt('')
plt.scatter(data3[:,0],data3[:,1],color="b")
data4 = np.loadtxt('')
plt.scatter(data4[:,0],data4[:,1],color="k")
# 给定的⽬标向量
objdata = np.loadtxt('')
plt.scatter(objdata[:,0],objdata[:,1],color="y")
plt.show()
# objdata 为待预测的数据集,Trains是已知的数据集(该数据集的类别是四类,分别对应0,1,2,3)
#vstack()能够合并所读取的数据集
Trains = np.vstack([data1,data2,data3,data4])
#为已知数据集,创建分类标签。
TrainsClass = np.vstack([np.zeros((50,1)),np.ones((50,1)),s((50,1)),s((50,1))])
②计算已知类别数据集中的点与当前点之间的距离:
# 开始假设k值 k=10
k=10
for i in range(15):
# 求已知类别的值与位置类别点的距离
dist =(((Trains - objdata[i,:])**2).sum(1))**0.5
# 对算出的距离进⾏排序,由⼩到⼤,所排的内容是已知数据集数据的下标
# 这个下标与已知数据集的标签下标⼀致,可以借此到数据所对应的标签
sortedDist = dist.argsort()
③将距离升序排列,然后选取距离最⼩的k个点。
#classCount空字典是⽤来,做分类计数。这是判断最终分类结果的关键。
团结湖三中classCount ={}
# k =10
for i in range(k):
# voteLabel 获得的是Trains数据集的分类
voteLabel =str(TrainsClass[sortedDist[i]])
#get 获取字典的值,参数1为键,参数2为默认的值。默认值在键所对应的值不存在的时候被触发,返回的是键所对应的值。
#确定前K个点所在类别的出现频率
classCount[voteLabel]= (voteLabel,0)+1
④选择频率最⾼的类别作为当前点的预测类别。
maxType =0
maxCount =-1
# 出出现次数最多的类别
for key,value in classCount.items():
if value > maxCount:
maxType = key,
maxCount = value
⑤上述的四个步骤执⾏⼀次可以分辨⼀个⽬标数据集中的向量值,但是在实际的判断中,我们不⽌判断⼀个。
#将所有类别最⼤的值存放在⼀个数组中
if(maxType ==('[0.]',)):
result.append(0)
elif(maxType ==('[1.]',)):
result.append(1)
elif(maxType ==('[2.]',)):
result.append(2)
else:
result.append(3)
#打印该数据可知不同⽬标向量对应的分类
print(result)
⑥对结果进⾏可视化。
for i in range(15):
if(result[i]==0):
type0 = plt.scatter(objdata[i,0],objdata[i,1],s=40,color="r",marker='x')
elif(result[i]==1):
type1 = plt.scatter(objdata[i,0],objdata[i,1],color="g",marker='x')
elif(result[i]==2):
type2 = plt.scatter(objdata[i,0],objdata[i,1],color="b",marker='x')
elif(result[i]==3):
type3 = plt.scatter(objdata[i,0],objdata[i,1],color="k",marker='x')
#添加图例
plt.legend((type0,type1, type2, type3),('0 class','1 class','2 class','3 class'))
plt.show()
上述操作所得结果如下:
[外链图⽚转存失败,源站可能有防盗链机制,建议将图⽚保存下来直接上传(img-lbxyw44F-1609429162604)
(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201126105503883.png)]
3 改进:
在上述的操作中,我们会发现K的取值是我们随意给的值,没有科学依据。因此我们可以将已知分类的数据集划分成训练集和测试集,当测试集的数据被准确预测(在实际实现中很难做到准确预测,只能是尽可能的趋向结果值)后,就可以确定K的取值。
①关于上述的趋向,如何判断:
#不同k值对应的准确性
# 参数1为knn算法分类出的结果数组,参数2为测试集真实的标签,n为测试集合的数据个数
def kvalue(rarry,oarray,n):
count =0
for i in range(n):
if(rarry[i]==oarray[i]):
count = count +1
return(count/n)
②为了便于操作,将KNN的分类⽅式抽象成⼀个函数:
k-近邻分类函数:knnfunction
参数:
train为已知分类的数据集,target为未知分类的数据集,trainclass为已知分类数据集的分类值集合,k为欧式距离未分类点最近的点的个数,n为未知分类的待测数据集的数据条数。
precisionk =[]#精确度集合
# K近邻算法
def knnfunction(train,target,tarinclass,k,n):
result =[]
for i in range(n):
dist =(((train - target[i,:])**2).sum(1))**0.5
sortedDist = dist.argsort()
classCount ={}
for i in range(k):
voteLabel =str(tarinclass[sortedDist[i]])
classCount[voteLabel]= (voteLabel,0)+1
maxType =0
maxCount =-1
for key,value in classCount.items():
if value > maxCount:
maxType = key,
maxCount = value
if(maxType ==('[0.]',)):
result.append(0)
elif(maxType ==('[1.]',)):
result.append(1)
elif(maxType ==('[2.]',)):
result.append(2)
else:
result.append(3)
print("⽬标向量的分类结果:",result)
# 精确度
precisionk.append(kvalue(result,targetnclass,n))
for i in range(n):
if(result[i]==0):
type0 = plt.scatter(target[i,0],target[i,1],s=40,color="r",marker='x')
elif(result[i]==1):
type1 = plt.scatter(target[i,0],target[i,1],color="g",marker='x')
elif(result[i]==2):少年军校活动被写入哪部法律?
type2 = plt.scatter(target[i,0],target[i,1],color="b",marker='x')
elif(result[i]==3):
type3 = plt.scatter(target[i,0],target[i,1],color="k",marker='x')
plt.show()
③ 也可以将计算k精确度与k近邻的算法的两个函数抽象成⼀个。
4 截⽌到3中改进的第⼆步,代码如下:
基利冈萨雷斯import numpy as np
import matplotlib.pylab as plt
import operator
data1 = np.loadtxt('')#读取数据集
plt.scatter(data1[:,0],data1[:,1],color="r",label ="0 class")#绘制散点图
data2 = np.loadtxt('')
plt.scatter(data2[:,0],data2[:,1],color="g",label ="1 class")
data3 = np.loadtxt('')
plt.scatter(data3[:,0],data3[:,1],color="b",label ="2 class")
data4 = np.loadtxt('')
plt.scatter(data4[:,0],data4[:,1],color="k",label ="3 class")
objdata = np.loadtxt('')
plt.scatter(objdata[:,0],objdata[:,1],color="y",marker='X')
plt.show()
# objdata 为待预测的数据集,Trains是已知的数据集(该数据集的类别是四类,分别对应0,1,2,3)Trains = np.vstack([data1,data2,data3,data4])
TrainsClass = np.vstack([np.zeros((50,1)),np.ones((50,1)),s((50,1)),s((50,1))]) k =10
# 为验证k的取值⽽划分的测试集和训练集
np.random.shuffle(data1)
data11 = data1[:46,:]
data12 = data1[46:50,:]
np.random.shuffle(data2)
data21 = data2[:46,:]
data22 = data2[46:50,:]
np.random.shuffle(data3)
data31 = data3[:46,:]
data32 = data3[46:50,:]
np.random.shuffle(data4)
data41 = data4[:46,:]
data42 = data4[46:50,:]
trainn = np.vstack([data11,data21,data31,data41])
trainnclass = np.vstack([np.zeros((46,1)),np.ones((46,1)),s((46,1)),s((46,1))]) targetn = np.vstack([data12,data22,data32,data42])
targetnclass = np.vstack([np.zeros((4,1)),np.ones((4,1)),s((4,1)),s((4,1))])
#不同k值对应的准确性
# 参数1为knn算法分类出的结果,参数2为⽬标集合真实的标签,n为⽬标集合的数据个数
def kvalue(rarry,oarray,n):
count =0
for i in range(n):
if(rarry[i]==oarray[i]):
count = count +1
return(count/n)
precisionk =[]#精确度集合
# K近邻算法
def knnfunction(train,target,tarinclass,k,n):
result =[]
婆罗多舞for i in range(n):
dist =(((train - target[i,:])**2).sum(1))**0.5
sortedDist = dist.argsort()
classCount ={}
for i in range(k):
voteLabel =str(tarinclass[sortedDist[i]])
classCount[voteLabel]= (voteLabel,0)+1
maxType =0
maxCount =-1
for key,value in classCount.items():
if value > maxCount:
maxType = key,
maxCount = value
if(maxType ==('[0.]',)):
result.append(0)
elif(maxType ==('[1.]',)):
result.append(1)
elif(maxType ==('[2.]',)):
result.append(2)
else:
result.append(3)
print("⽬标向量的分类结果:",result)
# 精确度
precisionk.append(kvalue(result,targetnclass,n))
约翰 纳什for i in range(n):
if(result[i]==0):
type0 = plt.scatter(target[i,0],target[i,1],s=40,color="r",marker='x')
elif(result[i]==1):

本文发布于:2024-09-23 07:19:38,感谢您对本站的认可!

本文链接:https://www.17tex.com/xueshu/326082.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:数据   分类   类别   已知   算法   距离
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议