k-近邻算法:存在一个样本集,并知道该样本集中每一个数据与所属分类(标签)的对应关系,当输入一个没有标签的新数据时,怎么判断该数据属于哪一个分类,这时就需要用到k-邻近算法。那么具体怎么用呢?选择距离该数据最近的k个最相似数据,并选出这k个数据中出现次数最多的分类,这个分类就是新数据的分类。
举例说明:假如我是一个女生,我身边的妹子都很漂亮并且能力都很强,那由此可知我长的是不是也应该差不多的好看呢(偷笑)?能力是不是也不算太弱呢?有点人以类聚物以群分的感觉哈~~~~不瞎扯了,咳咳,开始讲解代码
以下代码是在jupyter中进行的
准备:使用python导入数据
from numpy import *
import numpy as np
import operator#运算符模块
def createDataSet():
group = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])#numpy中的数组(4,2)
labels = ['A','A','B','B']#标签
return group,labels
测试一下我们创建的数据集是否正确
group, labels = createDataSet()
print(group,labels)
print(group.shape)#读取矩阵的长度
输出:
[[ 1. 1.1]
[ 1. 1. ]
[ 0. 0. ]
[ 0. 0.1]] ['A', 'A', 'B', 'B']
(4, 2)
准备好数据集,接下来当然就是k邻近算法啦,
该算法思想:找到距离某个新数据最近的k个点,并计算这k个点所属分类最的数量,从而找出落入点最多的分类。首先计算出这个新数据和数据集中各点的欧式距离,并排序。找出前k个数据
#k-近邻算法核心代码
#四个参数分别为:用于分类的输入向量inX,输入的训练样本集dataSet,标签向量labels,k表示用于选择最近邻居的数目
def classify0(x, dataSet, labels, k):
size = dataSet.shape[0]#读取第一维度的长度
diffMat = np.tile(x, (size, 1)) - dataSet
#tile(x,(4,1))在列方向上重复[1,1]1次,行4次,即创建一个数组和原数据集形状相同
sqDiffMat = diffMat ** 2
sqDistances = sqDiffMat.sum(axis = 1)#axis=1代表将一个矩阵的每一行向量相加
distances = sqDistances ** 0.5#开根号
sortedDisIndicies = distances.argsort()#排序
classCount = {}#定义一个字典
for i in np.arange(k):#找到前k个数据,放入字典中
voteIlabel = labels[sortedDisIndicies[i]]
classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
value = -1
for key in classCount:
if value < classCount[key]:
flag = key
value = classCount[key]
return flag
是不是有点看不懂了,没关系,最开始我也不懂。毕竟谁生下来都不是自带大神属性,开始剖析这段代码我相信大部分人到for循环的时候就差不多开始迷惑了,for循环中还有一个重要的知识点
python字典的get()函数
classCount.get(voteIlabel, 0)返回字典classCount中voteIlabel元素对应的值,若无,则进行初始化为0,初始化的值即为get()的第二个参数,
第一次遇到标签A,classCount.get(voteIlabel, 0)值为0,
第二次遇到标签A,classCount.get(voteIlabel, 0)时,值加1
上代码测试
import numpy as np
labels = ['A', 'A', 'B', 'B']
sortedDisIndicies =[1,2,3]
classCount = {}
for i in np.arange(3):
# 按照从小到大,依次取出相应的 label
voteIlabel = labels[sortedDisIndicies[i]]
print(voteIlabel,classCount.get(voteIlabel, 0))
# 如果字典中没该 label 就添加 value 为 1 ,如果有,则在原来基础上 value + 1
classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
print(voteIlabel,classCount[voteIlabel])
输出:
A 1
A 2
B 1
B 2
B 2
B 3
OK,到这,我们已经完成分类计数,接下来字典值比较
领出来再测一遍
print(classCount)
value = -1
#key是字典的键,classCount[key]该键对应的值
for key in classCount:
if value < classCount[key]:
flag = key
print(flag)
value = classCount[key]
print(value)
输出:
{'A': 2, 'B': 3}
A
2
B
3
OK ,现在应该全懂了,我们来个例子预测一下我们的算法吧
现在我们的数据集有四个数据,四个对应的标签
group, labels = createDataSet()#创建数据集
classify0([1,1], group, labels, 3)#测试[1,1]属于哪个分类,找最近的3个数据实验
输出:
'A'
第一个分类器就构造完成了,接下来就是测试分类器,见下篇吧
源码