第二章 k-近邻算法(kNN)
2.1k-近邻算法概述
定义:采用测量不同特征值之间的距离方法进行分类。
优点:精度高,对异常值不敏感、无数据输入假定。
缺点:计算复杂度高、空间复杂度高。
适用数据范围:数值型和标称型。
工作原理:存在一个训练样本集,样本集中的每个数据都存在标签,即我们知道每个数据属于哪个分类。输入没有标签的新数据之后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本集中特征最相似数据的分类标签。一般来说,只选择前k个最相似的数据,所以叫做k-近邻算法。通常,k是不大于20的整数。最后选择k个相似数据中出现最多的分类,作为新数据的分类。
一般流程:
1.收集数据
2.准备数据:距离计算所需要的数值,最好是结构化的数据格式。
3.分析数据
4.训练算法:不适用于kNN。
5.测试算法:计算错误率。
6.使用算法:首先输入样本数据和结构化的输出结果,然后运行k近邻算法判定输入数据属于哪个分类,最后应用计算出的分类执行后续处理。
2.1.1准备:使用Python导入数据
首先创建一个kNN.py文件如下:
#kNN.py
#两个包分别是科学计算包和运算符模块,这个模块中有运行kNN所需要的函数
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
然后,打开Windows PowerShell,进入kNN.py所在目录,输入python进入python交互式开发环境,导入刚才编辑的程序模块
import kNN
创建数据集
group,labels=createDataSet()
可以检查一下是否准确。现在我们有四组数据,每组有两个特征值。
2.1.2实施kNN分类算法
伪代码:
对未知分类属性的数据集中的每个点依次执行以下操作:
1.计算已知类别数据集中的点与当前点的距离
2.按照距离递增次序排序
3.选取与当前点距离最小的k个点
4.确定前k个点所在类别的出现频率
5.返回前k个点出现频率最高的类别作为当前点的预测分类
代码解释
#定义了一个名为classify0的函数,有四个输入值:用于分类的新数据,训练样本,标签,近邻数目,标签数目和训练样本的行数应当相同
#dataSet 是一个array,其中的数据类型必须相同,array.shape 可以得到有几个实例以及每个实例有几个特征,此处得到的是实例的个数
#tile函数位于python模块 numpy.lib.shape_base中,他的功能是重复某个数组。比如tile(A,n),功能是将数组A重复n次,构成一个新的数组
#如果inX=[0,0],dataSetSize=4,tile(inX,(dataSetSize,1))=array([[0,0],[0,0],[0,0],[0,0]])
#dataSet=array([[1,1.1],[1,1],[0,0],[0,0.1]])
#.sum(axis=1)就是将一个矩阵的每一行向量相加,换句话说就是每个[]里面的数相加
#distances=array([1.49,1.41,0,0.1])
#.argsort()出现下标array([2,3,0,1])
#classCount={}字典
#classCount[voteIlabel]=classCount.get(voteIlabel,0)+1 具体解释https://blog.csdn.net/weixin_38705903/article/details/79231551
#第二个域的值进行排序,逆序,classCount.iteritems()返回迭代器,sortedClassCount[0][0]返回的第一个值的第一个域
def classify0(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
sortedDistIndicies=distances.argsort()
classCount={}
#选择距离最小的k个点
for i in range(k):
voteIlabel=labels[sortedDistIndicies[i]]
classCount[voteIlabel]=classCount.get(voteIlabel,0)+1
#排序
sortedClassCount=sorted(classCount.iteritems(),key=operator.itemgetter(1),reverse=True)
return sortedClassCount[0][0]
注意:Python 3.6.0改为
sortedClassCount=sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
然后在交互式界面中输入
kNN.classify0([0,0],group,labels,3)
运行结果为B。
2.1.3测试分类器
可以使用已知答案的数据,用分类器给出错误结果的次数除以测试执行次数,得到错误率。
2.2示例:使用k近邻算法改进约会网站的配对效果
步骤:
1.收集数据:准备文本文件
2.准备数据:使用Python解析文本文件
3.分析数据:使用Matplotlib画二维扩散图。
4.训练算法:此步骤不适用于k近邻算法。
5.测试算法:使用海伦提供的部分数据作为测试样本。
6.使用算法:产生简单的命令行程序,然后海伦可以输入一些特征数据以判断对方是否为自己喜欢的类型。
2.2.1准备数据:从文本文件中解析数据
datingTestSet.txt 1000个实例,3个特征 创建名为file2matrix的函数,加入kNN.py。
def file2matrix(filename):
fr=open(filename)
array0lines=fr.readlines()
number0fLines=len(array0lines)
#得到行数,创建空矩阵
returnMat=zeros((number0fLines,3))
classLabelVector=[]
index=0
for line in array0lines:
#移除回车
line=line.strip()
listFormLine=line.split('\t')
returnMat[index,:]=listFormLine[0:3]
#取出最后一列的label
classLabelVector.append(int(listFromLine[-1]))
index +=1
return returnMat,classLabelVector
TabError: inconsistent use of tabs and spaces in indentation
这个错误是混用了Tab键和四个空格
然后在交互式界面输入
import kNN
datingDataMat,datingLabels=kNN.file2matrix('datingTestSet2.txt')
2.2.2 分析数据:使用Matplotlib创建散点图
在交互式界面输入
>>> import matplotlib
>>> import matplotlib.pyplot as plt
>>> fig=plt.figure()
>>> ax=fig.add_subplot(111)
>>> ax.scatter(datingDataMat[:,1],datingDataMat[:,2],15.0*array(datingLabels),15*array(datingLabels))
>>> plt.show()
得到
待续