简单的KNN算法
#添加编码方式
# -*- coding: utf-8 -*-
from numpy import *
import operator
# 准备数据
def createDataSet():
group = array([[1.0, 1.1], [1.0, 1.0], [0, 0], [0, 0.1]])
labels = ['A', 'A', 'B', 'B']
return group, labels
# 使用KNN找出距离最近的类别标签
# inX:待预测的样本向量
# dataSet:训练样本集
# labels:训练样本集对应的类别标签,长度与dataSet的长度一致
# k:从dataSet中找出离inX距离最近的k个样本
def classifyKNN(inX, dataSet, labels, k):
dataSetNum = dataSet.shape[0] # 样本数,dataSet是个矩阵/二维数组,shape属性返回矩阵的形状,即行数列数信息,行数即为样本个数
diffMat = tile(inX, (dataSetNum, 1)) - dataSet # tile是numpy库中的拼接函数,(dataSetNum,1)表示副本的行列数,这样做是为了让inX与dataSet的每一行做运算
sqDiffMat = diffMat ** 2 #inX与每个训练样本对应特征差值的平方
sqDistances = sqDiffMat.sum(axis=1)
distances = sqDistances ** 0.5 #按列对平方差值矩阵求和,之后再开方,即为inX与每个训练样本的欧式距离
sortedDistanceIdx = distances.argsort() # 距离从小到大的索引值,sortedDistanceIdx中存放的是值从小到大的distances的索引值
classCount = {} #统计类别数
for i in range(k): #0~k-1
voteLabel = labels[sortedDistanceIdx[i]] #sortedDistanceIdx中存放的是distances的索引值,其与训练集的labels是相对应的,只不过sortedDistanceIdx存储的是距离从小到大的索引,若此时i=0,则sortedDistanceIdx[i]值为离inX最近的训练样本的索引值,labels[sortedDistanceIdx[i]]值为这个离的最近的训练样本的类别
classCount[voteLabel] = classCount.get(voteLabel, 0) + 1 #类别字典对应key的value增1
sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True) #sorted是python内置的排序方法,classCount.iteritems()得到字典的key-value对列表,用来迭代,key指使用哪个特征来排序,reverse表示降序or升序
return sortedClassCount[0][0] #因为是降序排列,sortedClassCount[0][0]表示出现次数最多的类别,sortedClassCount[0][1]表示最多类别的出现次数
# 执行
g, l = createDataSet()
print classifyKNN((0, 0), g, l, 3)
小测试
a = (4, 1, 3)
b = operator.itemgetter(2, 0)
print b(a)
结果为(3, 4)
students = [('carl', 'c', 66), ('sarah', 'a', 93), ('bill', 'c', 71)]
s = sorted(students, key=lambda student: student[2], reverse=True) #lambda表达式
t = sorted(students, key=operator.itemgetter(0), reverse=False) #operator.itemgetter
print s, '\n', t
结果为[('sarah', 'a', 93), ('bill', 'c', 71), ('carl', 'c', 66)]
,其中,students是list,lamdba表达式是用第2个特征来做排序的,operator.itemgetter是用第0个特征来排序,排序结果都是list。
[('bill', 'c', 71), ('carl', 'c', 66), ('sarah', 'a', 93)]
students = {'carl': 66, 'sarah': 93, 'bill': 71}
s = sorted(students.iteritems(), key=lambda student: student[1], reverse=False)
t = sorted(students.iteritems(), key=operator.itemgetter(1), reverse=False)
print s, '\n', t
结果为[('carl', 66), ('bill', 71), ('sarah', 93)]
,其中,students是字典dict,要先使用iteritems方法获取key-value的迭代对象,这里的key都是用第1个特征排序,lambda表达式和operator.itemgetter的效果一样,排序结果都是list。
[('carl', 66), ('bill', 71), ('sarah', 93)]