k-近邻

Posted mmい

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了k-近邻相关的知识,希望对你有一定的参考价值。

前言:本系列文章旨在熟悉算法的同时增强编程能力,使用的都是很小的数据集,代码是自己一点点码出来的,如有错误还望指正,O(∩_∩)O谢谢

一个简单的例子

关于k近邻算法的理论我就不多说了,直接上一个非常简单快速的实现:

  • 分类函数的输入参数:
    • 待分类样本testX
    • 训练集dataSet
    • 训练样本标签dataSet
    • k值
  • 在classify函数中,距离计算k个邻居的求解以及最后投票的规则我都使用函数给出,是因为这三个值可以用不同的方法得到。比如距离计算可以使用欧氏距离、曼哈顿距离、皮尔逊相关系数等等;k个邻居可以是前k个邻居,也可以是以0.9的概率选择前k个邻居中的一个以0.1的概率选择剩余里的一个总共选择k个,也可以不是选择k个,比如第k个邻居的距离超过一个阈值时,我们可以不用非要取它,而只要k-1个邻居即可;最后投票的规则,我们可以给票加一些权重,比如越近的邻居的权重越高这样子;以函数的形式给出,之后做修改就更灵活,每次传入三个函数作为参数即可。
def classify(testX, dataSet, labels, k):
    dis = [];
    for i in range(len(dataSet)):
        dis.append(distance(testX, dataSet[i]))
    knnIndex = kNearstNeighbors(dis, k)
    testY = vote(knnIndex, labels)
    return testY

# calculate the distance between test sample and train sample
def distance(testX, trainX):
    sum = 0
    for i in range(len(testX)):
        sum += (testX[i]-trainX[i])*(testX[i]-trainX[i])
    return sum

# return the indexs of the k Nearst Neighbors
def kNearstNeighbors(dis, k):
    return np.argsort(dis)[0:k] 

# return the highest votes as test sample label  
def vote(knnIndex, labels):
    d = 
    for i in knnIndex:  
        # For key key, returns value or default if key not in dictionary                 
        d[labels[i]] = d.get(labels[i], 0) + 1 
    return max(d, key=d.get)       
  • 测试我的算法
if __name__=="__main__":
    dataSet = np.array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
    labels = ['A','A','B','B']
    testX = [0,0]
    print classify(testX, dataSet, labels, 3)
  • 在distance方法中我们直接计算了训练样本和测试样本的欧氏距离作为它们之间的距离度量,但是我们忽略了一件事:不同特征的规模是不一样的,如果对输入数据不做任何处理,直接进行距离度量,会导致距离严重偏向那些取值范围较大的属性,相当于隐含的增加了属性的权重(上面angel例子我只是给出了很简单的样本,规模相当,所以没有进行归一化)。对数据进行归一化操作:
def autoNorm(dataSet):
    minVals = dataSet.min(0) # 得到每一列的最小值
    maxVals = dataSet.max(0) # 得到每一列的最大值
    ranges = maxVals - minVals
    normDataSet = zeros(shape(dataSet))
    m = dataSet.shape[0]
    normDataSet = dataSet - tile(minVals, (m,1))
    normDataSet = normDataSet/tile(ranges, (m,1))   #element wise divide
    return normDataSet, ranges, minVals

总结

  • 使用这个算法的执行效率非常低,它是lazy的学习算法,也就是当测试样本来时才进行模型的计算。对于每一个测试样例,需要计算该测试样例与所有训练样本的距离,而每一个距离计算又涉及所有特征的浮点计算。在我的另一篇博客中有一个优化的算法实现kdTree.
  • k-近邻算法必须保存全部数据集,如果训练数据集很大,必须使用大量的存储空间。
    • 优点:精度高、对异常值不敏感、无数据输入假定;
    • 缺点:计算复杂度高、空间复杂度高;
    • 适用数据范围:数值型和标称型;

以上是关于k-近邻的主要内容,如果未能解决你的问题,请参考以下文章

机器学习_K近邻代码详解

《统计学习方法》笔记--K近邻

k-近邻算法

K近邻法

k-近邻算法学习

K-近邻算法(knn)