- 简介
k-近邻(kNN, k-NearestNeighbor)算法是一种分类算法。
简单来说,KNN可以看成:有一堆你已经分好类的数据,并已给它们分好类。将它们映射到平面坐标内,当有一个新数据进入的时候,就开始计算新数据点和所有已知数据的距离(使用欧式距离计算两点的距离),然后挑出离这个数据最近的K个已知点(一般情况下K小于20),看这K个点属于什么类型,然后用少数服从多数的原则,给新数据归类。再简单点说也就是近朱者赤近墨者黑。
特点
-
优点
精度高、对异常值不敏感、无数据输入假定。
算法思路较为简单,易于实现;
当有新样本要加入训练集中时,无需重新训练(即重新训练的代价低);
计算时间和空间线性于训练集的规模(在一些场合不算太大)。
-
缺点
计算复杂度高、空间复杂度高,因此分类速度慢
各属性的权重相同,影响了准确率
样本库容量依赖性较强
K值不好确定
-
适用数据范围
数值型和标称型
-
开发流程
收集数据:随意使用任何方法收集成csv或者文本文件
准备数据:距离计算所需要的数值,最好是结构化的数据格式
分析数据:任何方法(可以画二维扩散图)
训练算法:k-近邻算法不需要这个步骤
测试算法:计算错误率
使用算法:输入样本数据和结构化的输出结果,然后运行 k-近邻算法判断输入数据分类属于哪个分类,最后对计算出的分类执行后续处理。
-
代码
from numpy import *
import operator
def createDataSet():
group = array([[1.0, 1.1], [1, 0.9], [0, 0], [0.1, 0.1]])
lables = ['A', 'A', 'B', 'B']
return group, lables
def classify0(inX, dataSet, labels, k):
dataSetSize = dataSet.shape[0]
n = tile(inX, (dataSetSize, 1))
DiffMat = n - dataSet
sqDiffMat = DiffMat ** 2
sqDistances = sqDiffMat.sum(axis=1)
distances = sqDistances ** 0.5 # 到这里求解了欧式距离(并构成了一个ndarray)
sortedDistances = distances.argsort() # 根据排名作为索引 Index
classCount = {}
for i in range(k):
voteIlabel = labels[sortedDistances[i]]
classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
# 选出了距离最小的k个点,并且做了一个简单的统计
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True) # 按照第一个(从0开始数)进行排序
return sortedClassCount[0][0] # 返回的出现次数最多的那个标签
group, labels = createDataSet()
# 随意定义一个点进行分类测试
x = [1, 1]
print(classify0(x, group, labels, 2))