算法概述
-
优点
- 精度高、对异常值不敏感、无数据输入假定。 缺点
- 计算复杂度高、空间复杂度高。 试用数据范围
- 数值型和标称型
工作原理:将新数据的每个特征与样本集中数据对应特征进行比较,计算之间的距离值,选取样本数据集中前k个最相似的数据。
-
伪代码
-
- 计算已知类别数据集中的点与当前点之间的距离
- 按照距离递增次序排序
- 选取与当前点距离最小的k个点
- 确定前k个点所在类别的出现频率
- 返回前k个点出现频率最高的类别作为当前点的预测分类
具体 python 实现
from numpy import *
import operator
from os import listdir
def classify0(inX, dataSet, labels, k):
dataSetSize = dataSet.shape[0]
diffMat = tile(inX, (dataSetSize, 1)) - dataSet
sqDiffMat = diffMat**2
sqDistances = sqDiffMat.sum(axis=1)
distances = sqDistances**0.5
sortedDistIndicies = distances.argsort()
classCount = {}
for i in range(k):
voteIlabel = labels[sortedDistIndicies[i]]
classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
sortedClassCount = sorted(classCount.iteritems(),key=operator.itemgetter(1),reverse=True)
return sortedClassCount[0][0]
程序中使用的是欧氏距离公式
d=(xA0−xB0)2+(xA1−xB1)2−−−−−−−−−−−−−−−−−−−−−−−−√
diffMat=tile(inX,(dataSetSize,1))-dataSet
- 这句话是利用 numpy 中的tile函数, tile 函数把测试样本 inX 复制样本集次数建立新数组,之后与各项特征做差得到 diffMat
sqDistances=sqDiffMat.sum(axis=1)
- 规定了求和的坐标轴为横轴 1
sortedDistIndicies=distances.argsort()
- 返回的是排序后的原索引序号
classCount[voteIlabel]=classCount.get(voteIlabel,0)+1
- 其中
dict.get(key, default=None)
在字典中查询key对应的value,没有则返回0.这句话是统计前k个最近距离样本对应的类别出现的次数
sortedClassCount=sorted(classCount.iteritems(),key=operator.itemgetter(1),reverse=True)
- 首先看
sorted(iterable, cmp=None, key=None, reverse=False)
classCount.iteritems()
以迭代器对象返回键值对儿(Python3中不再支持)。
key 参数是用列表元素的某个属性或函数进行作为关键字,有默认值,迭代集合中的一项。key接受一个函数,这个函数只接受一个元素,形式如下
def f(a):
return len(a)
- key接受的函数返回值,表示此元素的权值,sort将按照权值大小进行排序
key=operator.itemgetter(1)
operator模块提供的itemgetter函数用于获取对象的哪些维的数据,参数为一些序号(即需要获取的数据在对象中的序号),下面看例子。
a = [1,2,3]
>>> b=operator.itemgetter(1) //定义函数b,获取对象的第1个域的值
>>> b(a)
2
>>> b=operator.itemgetter(1,0) //定义函数b,获取对象的第1个域和第0个的值
>>> b(a)
(2, 1)
- 要注意,operator.itemgetter函数获取的不是值,而是定义了一个函数,通过该函数作用到对象上才能获取值。
文本转换 NumPy 程序
def file2matrix(filename):
fr = open(filename)
# get the number of lines in the file
numberOfLines = len(fr.readlines())
returnMat = zeros((numberOfLines, 3)) # prepare matrix to return
classLabelVector = [] # prepare labels return
fr = open(filename)
index = 0
for line in fr.readlines():
line = line.strip()
listFromLine = line.split('\t')
returnMat[index, :] = listFromLine[0:3]
classLabelVector.append(int(listFromLine[-1]))
index += 1
return returnMat, classLabelVector
line=line.strip()
- 删除字符串中开头、结尾处空白符
listFromLine=line.split('\t')
- 按’\t’字符分割字符串
数值归一化
newValue=oldValue−minmax−min