参考博文:
KNN算法:
http://blog.csdn.net/c406495762(非常详细,推荐)
https://www.cnblogs.com/ybjourney/p/4702562.html
函数相关:
https://blog.csdn.net/qq_18433441/article/details/54897250
https://www.cnblogs.com/jyxbk/p/8664817.html
https://www.cnblogs.com/yyxf1413/p/6253995.html
初学python 代码中很多函数不了解,自己进一步做了注释
# -*- coding: utf-8 -*-
import numpy as np
import operator
"""
函数说明:创建数据集
Parameters:
无
Returns:
group - 数据集
labels - 分类标签
"""
def createDataSet():
#四组二维特征
group=np.array([[1,101],[5,89],[108,5],[115,8]])
#分别表示四个点:爱情片,爱情片,动作片,动作片
#四组特征标签
labels=['爱情片','爱情片','动作片','动作片']
return group,labels
"""
函数说明:kNN算法,分类器
算法描述:1)计算测试数据与各个训练数据之间的距离;
2)按照距离的递增关系进行排序;
3)选取距离最小的K个点;
4)确定前K个点所在类别的出现频率;
5)返回前K个点中出现频率最高的类别作为测试数据的预测分类。
Parameters:
inX - 用于分类的数据(测试集)
dataSet - 用于训练的数据(训练集)
labes - 分类标签
k - kNN算法参数,选择距离最小的k个点
Returns:
sortedClassCount[0][0] - 分类结果
"""
def classify0(inX,dataSet,labels,k):
#shape[0]返回dataSet的行数
dataSetSize=dataSet.shape[0]
"""
>>> b = np.array([[1, 2], [3, 4]])
>>> np.tile(b, 2) #沿X轴复制2倍
array([[1, 2, 1, 2],
[3, 4, 3, 4]])
>>> np.tile(b, (2, 1))#沿X轴复制1倍(相当于没有复制),再沿Y轴复制2倍
array([[1, 2],
[3, 4],
[1, 2],
[3, 4]])
"""
#在列方向上重复inX共1次(横向),行方向重复inX共dataSetSize次(纵向)
#将测试集大小扩展为与训练集一样大,相减的差即为点之间的距离
diffMat=np.tile(inX,(dataSetSize,1))-dataSet
#二维特征相减后平方
sqDiffMat=diffMat**2
#sum(0)列相加,sum(1)行相加
sqDistances=sqDiffMat.sum(axis=1)
"""
a = np.array([[0, 2, 1]])
print a.sum()
print a.sum(axis=0)
print a.sum(axis=1)
结果分别是:3, [0 2 1], [3]
b = np.array([0, 2, 1])
print b.sum()
print b.sum(axis=0)
print b.sum(axis=1)
结果分别是:3, 3, 运行错误:'axis' entry is out of bounds
可知:对一维数组,只有第0轴,没有第1轴
c = np.array([[0, 2, 1], [3, 5, 6], [0, 1, 1]])
print c.sum()
print c.sum(axis=0)
print c.sum(axis=1)
结果分别是:19, [3 8 8], [ 3 14 2]
"""
#开方,计算距离(欧氏距离)
distances=sqDistances**0.5
#返回distances中元素从小到大排序后的索引值
sortedDistIndices=distances.argsort()
"""
x=np.array([1,4,3,-1,6,9])
y=x.argsort()
>>>y=array([3,0,2,1,4,5])。
argsort()函数是将x中的元素从小到大排列提取其对应的index(索引),
然后输出到y。例如:x[3]=-1最小,所以y[0]=3,x[5]=9最大,所以y[5]=5
"""
#定一个记录类别次数的字典
classCount={}
#取出前k个元素的类别(距离与测试集最近的k个类别)
for i in range(k):
#当前标签
voteIlabel=labels[sortedDistIndices[i]]
#计算类别次数
#dice.get(k,default=None),字典的get()方法,返回指定键的值,如果值
#不在字典中返回默认值
classCount[voteIlabel]=classCount.get(voteIlabel,0)+1
#python3中用items()替换python2中的iteritems()
#key=operator.itemgetter(1)根据字典的值进行排序
#key=operator.itemgetter(0)根据字典的键进行排序
#reverse降序排序字典
sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
#返回次数最多的类别,即所要分类的类别
return sortedClassCount[0][0]
if __name__=='__main__':
#当.py文件被直接运行时,if __name__ == '__main__'之下的代码块将被运行;当
#.py文件以模块形式被导入时,if __name__ == '__main__'之下的代码块不被运行。
#创建数据集
group,labels=createDataSet()
#测试集
test=[101,20]
#KNN分类
test_class=classify0(test,group,labels,3)
#打印分类结果
print(test_class)