学习笔记——knn
首先,第一次写博客这样的东西着实还蛮不知道怎么写的。
所以本文章只是自己的一点代码编写,过程以及一些问题的总结。比较private
此次程序仅是knn分类的一个完成,以及小测试
代码首先是生成一个对应的数据
from numpy import *
import operator
def creatdataset():
group = array([[1,1.1],[1,1],[0,0],[0,1]])
labels = ['a','a','b','b']
return group, labels
其中用到的第三方库为numpy ,是在python中比较常用的科学计算包,用于一般的矩阵计算,线性代数问题以及傅里叶变换
其中array用于给group定义一个4行,三列的矩阵。labels用于存放标签,ps:也就是用来分类说明的。
creatdataset函数,其实也就是对训练集进行的生成,以及保存。
knn算法演示
def classify0(inX, dataset, labels,k):
datasetsize = dataset.shape[0]
diffmat = tile(inX, (datasetsize, 1)) - dataset
sq_diffmat = diffmat**2
sq_distances = sq_diffmat.sum(axis=1)
distances = sq_distances ** 0.5
sortedistindicis = distances.argsort()
classcount={}
for i in range(k):
votelabel = labels[sortedistindicis[i]]
classcount[votelabel] = classcount.get(votelabel, 0) + 1
sortedclasscount = sorted(classcount.items(),
key=operator.itemgetter(1), reverse=True)
return sortedclasscount[0][0]
knn 的分类其实就是对 输入的2维值或者3维(这个看训练集中定义的数组类型)进行一个欧氏距离的计算
计算输入的inX的 xA,xB之间的距离,通过距离最小,对输入的位置进行分类。
其中shape[0],是返回训练集中的行数进行,所以说datasetsize其实就是4,tile(inX, (datasetsize,1))的效果其实就是
tile([0,0], (4, 1))
array([[0,0],[0,0],[0,0],[0,0]])
###也就是 diffmat进行了一个4行1列矩阵的减法
diffmat**2 自然不用说是在平方,sqdistance.sum(axis =1)这里还是蛮有意思的,axis=0表示参数的列,axis = 1表示参数的行
所以正好完成了参数中 x,y的和计算。然而后面的argsort就很有意思了,下面来介绍一下argsort()函数的一个测试
argsort,从英文的角度上来说,arg其实是争议的,sort我们很熟悉了分类。也就是说函数进行了排序,而且还是比较特别的排序,可见下演示
import numpy as as
q=as.array([1,2,3,-1,4,8])
print(q.argsort())
([3,0,2,1,4,5])
这里 显示的 其实内核中argsort()进行了从小到大的一个排序,但是·为什么输出的结果却是(3,0,2,1,4,5),眼尖的话其实很容易就发现了,q[3]=-1 是的是最小的那个数,q[5]=8最大。所以说明argsort()其实排序了,不过输出为index值。很神奇,这也说明了python的严谨性,程序员不会得到它的值,而是拿到了它的index。这样也就不会轻易的在后面的处理中轻易改变一个重要的参数。
接下来就是对对比计算的 输入值进行遍历 应为训练集中的个数为4则,k的取值为3即可。
其中classcount是一个字典,其实就存入了a,b和其进行对比后重复出现的次数
classcount[votelabels]其实就等于classcount[a]和classcount[b],为了更清楚了看到整个过程,所以对主要的参数进行显示
def classify0(inX, dataset, labels,k):
datasetsize = dataset.shape[0]
diffmat = tile(inX, (datasetsize, 1)) - dataset
sq_diffmat = diffmat**2
sq_distances = sq_diffmat.sum(axis=1)
distances = sq_distances ** 0.5
sortedistindicis = distances.argsort()
print(sortedistindicis)
classcount={}
for i in range(k):
votelabel = labels[sortedistindicis[i]]
classcount[votelabel] = classcount.get(votelabel, 0) + 1
print(classcount)
sortedclasscount = sorted(classcount.items(),
key=operator.itemgetter(1), reverse=True)
return sortedclasscount[0][0]
[2 3 1 0]
{'b': 1}
{'b': 2}
{'b': 2, 'a': 1}
b
以上为结果,在输入[0,0]时确认分类为b,对classcount中前3个进行了计数,着出现多的肯定只在前3个之内。
sortedclasscount = sorted(classcount.items(),
key=operator.itemgetter(1), reverse=True)
之后就是从大到小的排列 并且items是对字典进行读入,并且key=itemgetter(1),第一个领域进行读取,确定排列后得到的[0][0]位置上的 标志就是分类后的标志