K-邻近算法(k-NearestNeighbor,KNN),存在某一样本集,已经知道样本和对应的类别,当输入一个没有类别标识的数据时,找出与其“最相似”的K个样本,在这k个样本中,哪个类别的样本个数最多,我们就把该未知数据的类别归为此类。其中的相似性,可以利用距离来度量,而衡量距离的方法,可以是欧氏距离,闵可夫斯基距离,曼哈顿距离等等。

    KNN算法步骤:

    1,与处理数据

    2,根据距离公式求出,未知数据,到其他每个样本的距离

    3,把距离排列,选出距离最小的k个样本

    4,投票决定,该未知数据属于哪一个类别。

   一下根据实战来简单实现一下KNN。

# -*- coding: utf-8 -*-
"""
Created on Sat Mar 04 17:34:27 2017

@author: Abner
"""
from numpy import*
import operator

def createDataSet():
    group = array([[0, 1], [1.0, 1.0], [0, 0], [1, 1]])
    labels = ['A', 'A', 'B', 'B']
    return group, labels
    
def KNNclassify(inputData, dataSet, labels, k):
    DataSetRow = dataSet.shape[0]
    expandInputData = tile(inputData, (DataSetRow, 1))
    
    difference = expandInputData - dataSet
    sqdiff = difference**2
    tempSum = sqdiff.sum(axis = 1)
    distance = tempSum**0.5
    
    disIndex = distance.argsort()
    countNum = {}
    
    for i in xrange(k):
        voteLable = labels[disIndex[i]]
        countNum[voteLable] = countNum.get(voteLable, 0) + 1
    kNNDistance = sorted(countNum.iteritems(), key = operator.itemgetter(1), reverse = True)
    
    return kNNDistance[0][0]
        

group, labels = createDataSet()

print  KNNclassify([1, 0.2], group, labels, 3)

解释一下这段代码:

    首先生成一个样本集,本例生成了四个点,以及每个点所对应的类别。我们的距离度量为欧氏距离。

def createDataSet():
    group = array([[0, 1], [1.0, 1.0], [0, 0], [1, 1]])
    labels = ['A', 'A', 'B', 'B']
    return group, labels

    1,处理数据

DataSetRow = dataSet.shape[0]#多少个样本数据,也就是多少行
    expandInputData = tile(inputData, (DataSetRow, 1))#把未知数据,扩展为和样本数据一样的维数

    这里有必要说一下tile(A,reps) 这个函数,tile函数会把A按照reps从后向前依次对维度扩展,比如:

    A = [11, 12, 13], tile(A, 2),就是把A沿着第一个维度扩展依次,扩展的宽度就是原始列表的长度,于是:

A = [11, 12, 13]
print tile(A, 2)

[11 12 13 11 12 13]

    tile(A, (2, 1)),A的第一个维度不变,第二个维度扩展一次。

A = [11, 12, 13]
print tile(A, (2, 1))

[[11 12 13]
 [11 12 13]]

    tile(A, (2, 2, 2)),A的第一维,第二维,第三维各扩展一次

A = [11, 12, 13]
print tile(A, (2, 2, 2))

[[[11 12 13 11 12 13]
  [11 12 13 11 12 13]]

 [[11 12 13 11 12 13]
  [11 12 13 11 12 13]]]

   2,然后,求输入数据到训练样本的距离。

#计算距离
    difference = expandInputData - dataSet
    sqdiff = difference**2
    tempSum = sqdiff.sum(axis = 1)#按行求和
    distance = tempSum**0.5

   3,把距离排序

disIndex = distance.argsort()#不改变原始数据,但是会返回,数据从小到大排好后,在原始的位置

    argsort()函数,可看如下例子:

a = [11, 56, 3, 1, 88, 33, 96, 2]
index = argsort(a)

print index
print a

[3 7 2 0 5 1 4 6]
[11, 56, 3, 1, 88, 33, 96, 2]

    4,求距离最近的K个样本

countNum = {}
    for i in xrange(k):
        voteLable = labels[disIndex[i]]
        countNum[voteLable] = countNum.get(voteLable, 0) + 1
    kNNDistance = sorted(countNum.iteritems(), key = operator.itemgetter(1), reverse = True)

    .get()函数,.get(key, default),如果key值存在,get就返回相应的value,如果不存在就返回defult。例如:

dic = {"jack":15, "tom":20}

print dic.get("jack", 0)
print dic.get("jerry", 0)

15
0

    sorted函数

    5,输出类别

kNNDistance[0][0]

    从上述的代码中步骤中,我们可以看出来,每当输入一个数据,我们要计算该数据到每个样本的额距离,如果样本量很大,那么KNN的效率会很低。