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,那就取距离最小的那个向量对应的结果)
优缺点:
* 算法比较直接,容易实现
* 精度高、对异常值不敏感、无输入假定
* 计算复杂度高、空间复杂度也高
* 适用数据范围:数值型和标称型