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
DataSetRow = dataSet.shape[0]#多少个样本数据,也就是多少行
expandInputData = tile(inputData, (DataSetRow, 1))#把未知数据,扩展为和样本数据一样的维数
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]]
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]]]
#计算距离
difference = expandInputData - dataSet
sqdiff = difference**2
tempSum = sqdiff.sum(axis = 1)#按行求和
distance = tempSum**0.5
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]
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函数,请看:http://blog.csdn.net/hearthougan/article/details/60361126
kNNDistance[0][0]
从上述的代码中步骤中,我们可以看出来,每当输入一个数据,我们要计算该数据到每个样本的额距离,如果样本量很大,那么KNN的效率会很低。