k-近邻算法

k-近邻算法

#完整算法
def kNNClassify(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
    sorteDistIndicis = distances.argsort()
    classCount = {}
    for i in range(k):
        voteIlabel = labels[sorteDistIndicis[i]]
        classCount[voteIlabel] = classCount.get(voteIlabel,0) +1

    sortedClassCount = sorted(classCount.iteritems(),key=operator.itemgetter(1),reverse=True)
    return sortedClassCount[0][0]

接下来一句一句分析

def kNNClassify(inX, dataSet, labels, k):

参数说明

inX #需要计算的测试向量
dataSet #训练集(不包含结果集)
labels  #训练集对应的结果集
k #取k个与测试向量距离最近的进行预测

dataSetSize = dataSet.shape[0]

获取行数

import numpy
a=numpy.zeros((5,4),dtype='int32')
a.shape

输出为(5,4) 可以用

a.shape[0] #表示a的行数

diffMat = tile(inX, (dataSetSize,1)) - dataSet

所有的训练向量,一一与该需要测试的向量之差。得到差值矩阵

tile函数 
tile(A,(2,3))表示A的第一个维度重复3遍,然后第二个维度重复2遍

tile(inX, (dataSetSize,1))
[inX
 inX
 ...
 ...  >重复dataSetSize遍
 ...
 inX]

sqDiffMat = diffMat**2

得到差之后平方

sqDistances = sqDiffMat.sum(axis=1)

得到每一个训练特征向量与给定的测试向量的每一个特征值差的平方之和

sum(axis=1)

sum应该是默认的axis=0 就是普通的相加
而当加入axis=1以后就是将一个矩阵的每一行向量相加

distances = sqDistances**0.5

开根号

sortedDistIndicies - distances.argaort ()

argsort函数返回的是数组值从小到大的索引值

 >>> x = np.array([3, 1, 2])
    >>> np.argsort(x)
    array([1, 2, 0])
   #说明:数组中最小的是1,它的索引是1。
          数组中第二大的是2,它的索引是2。
          数组中最大的是3,它的索引是0。
          所以得到[1, 2, 0],以此类推

classCount = {}

字典变量

for i in range(k):

取k个与测试向量距离最近的进行预测

voteIlabel = labels[sortedDistIndicies[i]]

取距离给定测试向量第i小的结果集中对应的值

classCount[votellabel] = classCount.get(voteIlabel,0) + 1

把距离最近的k个点,根据结果值不同进行分类。

# Python 字典(Dictionary) get() 函数返回指定键的值,如果值不在字典中返回默认值。
classCount[votellabel] = classCount.get(voteIlabel,0) + 1

sortedClassCount = sorted(classCount.iteritems(),key=operator.itemgetter(1),reverse=True)

排序,根据各分类的数量进行降序排序

iteritems() #迭代输出字典的键值对
operator.itemgetter(1) #根据value进行排序

operator.itemgetter函数

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函数获取的不是值,而是定义了一个函数,通过该函数作用到对象上才能获取值。

sorted函数用来排序,sorted(iterable[, cmp[, key[, reverse]]])

其中key的参数为一个函数或者lambda函数。所以itemgetter可以用来当key的参数

a = [('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]

根据第二个域和第三个域进行排序

sorted(students, key=operator.itemgetter(1,2))

return sortedClassCount[0][0]

获取排序后的第一个key-value中的value即结果值

再来总结一下:
* 根据欧拉公式
计算训练集中每个向量与给定测试向量的距离
* 找出最近的k个向量(排序好的,从小到大)
* 在这最近的k个向量中,根据结果分类,获取最多结果的那个结果(如果分类后,每个结果对应的都是1,那就取距离最小的那个向量对应的结果)

优缺点
* 算法比较直接,容易实现
* 精度高、对异常值不敏感、无输入假定
* 计算复杂度高、空间复杂度也高
* 适用数据范围:数值型和标称型

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值