机器学习实战--Task01:K近邻算法

概述

k-近邻算法采用测量不同特征值之间的距离方法进行分类。

  • 优点:精度高、对异常值不敏感、无数据输入假定。
  • 缺点:计算复杂度高、空间复杂度高。
  • 适用数据范围:数值型的标称型

工作原理:存在一个样本数据集合(训练样本集),且每个数据都存在标签(我们知道样本集中每一数据与所属分类的对应关系)。输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本集中特征最相似数据(最近邻)的分类标签。一般来说,只选择前K个最相似的数据,最后,在k个最相似数据中出现次数最多的分类,作为新数据的分类。

k-近邻算法的一般流程:

1.收集数据:可以使用任何方法。
2.准备数据:距离计算所需要的数值。
3.分析数据:可以使用任何方法。
5.测试算法:计算错误率。
6.使用算法:首先输入样本数据和结构化的输出结果,然后运行k-近邻算法判定输入数据的分类,最后应用分类做后续处理。

准备:使用python导入数据

创建名为kNN.py的模块:

from numpy import *
import operator
#导入numpy模块和运算符模块
def creatDataSet():
	group=array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
	#创建二维数组,作为训练样本集
	labels=['A','A','B','B']     #设置标签
	return group,labels

结果:

>>> import kNN
>>> group,labels=kNN.creatDataSet()
>>> group
array([[1. , 1.1],
       [1. , 1. ],
       [0. , 0. ],
       [0. , 0.1]])
>>> labels
['A', 'A', 'B', 'B']    #labels包含的元素个数等于group矩阵行数
实施kNN算法:

使用函数classify0()实现kNN算法,其伪代码如下:
对未知类别属性的数据集中的每个点依次执行一下操作:
(1).计算已知类别数据集中的点与当前点之间的距离,采用欧式距离公式:
在这里插入图片描述
(2).按照距离递增次序排序
(3).选取与当前点距离最小的k个点
(4).确定前K个点所在类别的出现频率
(5).返回前k个点出现频率最高的类别作为当前点的预测分类

def classify0(inX,dataSet,labels,k):
	"""inX-用于分类的输入向量
	   dataSet-输入的训练样本集
	   labels-标签向量
	   k-选择最近邻居的数目"""
	dataSetSize=dataSet.shape[0]   #确定dataSet的行数
	diffMat=tile(inX,(dataSetSize,1))-dataSet     #tile函数实现在行方向上重复inX dataSetSize次,在列方向上重复1次;计算inX与训练样本集每个数值的差
	sqDiffMat=diffMat**2
	sqDistances=sqDiffMat.sum(axis=1)    #sqDiffMat每行元素相加
	distances=sqDistances**0.5
	sortedDistIndicies=distances.argsort()   #将distances中的元素从小到大排列,提取其对应的index(索引),然后输出到sortedDistIndicies
	classCount={}
	for i in range(k):           #确定前K个点所在类别的出现频率
		voteIlabel=labels[sortedDistIndicies[i]]
		classCount[voteIlabel]=classCount.get(voteIlabel,0)+1
	sortedClassCount=sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)   #按类别出现频率进行降序排序
	return sortedClassCount[0][0]    #返回出现频率最高的元素标签

上面代码中有几个陌生的函数,其用法见注释。

如何测试分类器

分类器并不会得到百分百正确的结果,我们可以使用多种方法检测分类器的正确率。分类器的性能也会受多种因素的影响,如分类器设置和数据集等。为了测试分类器的效果,我们可以使用已知答案的数据,当然答案不能告诉分类器,检验分类器给出的结果是否符合预期结果。通过大量的测试数据,我们可以得到分类器的错误率——分类器给出错误结果的次数除以测试执行的总数。错误率是常用的评估方法,主要用于评估分类器在某个数据集上的执行效果。

示例:使用k-近邻算法改进约会网站的配对效果

背景:

我的朋友海伦一直使用在线约会网站寻找适合自己的约会对象。尽管约会网站会推荐不同的人选,但她并不是喜欢每一个人。经过一番总结,她发现曾交往过三种类型的人:

  • 不喜欢的人
  • 魅力一般的人
  • 极具魅力的人

尽管发现了上述规律,但海伦依然无法将约会网站推荐的匹配对象归入恰当的分类。她觉得可以在周一到周五约会那些魅力一般的人,而周末则更喜欢与那些极具魅力的人为伴。海伦希望我们的分类软件可以更好地帮助她将匹配对象划分到确切的分类中。此外海伦还收集了一些约会网站未曾记录的数据信息,她认为这些数据更有助于匹配对象的归类。
在这里插入图片描述

1.准备数据:从文本文件中解析数据

海伦收集约会数据已经有了一段时间,她把这些数据存放在文本文件datingTestSet2.txt中,每个样本数据占据一行,总共有1000行。海伦的样本主要包含以下3种特征:

  • 每年获得的飞行常客里程数
  • 玩视频游戏所耗时间百分比
  • 每周消费的冰淇淋公升数

在将上述特征数据输入到分类器之前,必须将待处理数据的格式改变为分类器可以接受的格式。在kNN.py中创建名为file2matrix的函数,以此来处理输入格式问题。该函数的输入为文件名字符串,输出为训练样本矩阵和类标签向量。

def file2matrix(filename):
    #打开文件,得到文件行数
	fr=open(filename)   
	arrayOLines=fr.readlines() 
	numberOfLines=len(arrayOLines)
	returnMat=zeros((numberOfLines,3))
	classLabelVector=[]
	index=0
	for line in arrayOLines:
		line=line.strip()
		listFromLine=line.split('\t')
		returnMat[index,:]=listFromLine[0:3]
		classLabelVector.append(int(listFromLine[-1]))
		index+=1
	return returnMat,classLabelVector

结果:

>>> datingDataMat,datingLabels=kNN.file2matrix('datingTestSet2.txt')
>>> datingDataMat
array([[4.0920000e+04, 8.3269760e+00, 9.5395200e-01],
       [1.4488000e+04, 7.1534690e+00, 1.6739040e+00],
       [2.6052000e+04, 1.4418710e+00, 8.0512400e-01],
       ...,
       [2.6575000e+04, 1.0650102e+01, 8.6662700e-01],
       [4.8111000e+04, 9.1345280e+00, 7.2804500e-01],
       [4.3757000e+04, 7.8826010e+00, 1.3324460e+00]])
2.分析数据:使用Matplotlib创建散点图
>>> import matplotlib
>>> import matplotlib.pyplot as plt
>>> fig=plt.figure()
>>> ax=fig.add_subplot(111)
>>> ax.scatter(datingDataMat[:,1],datingDataMat[:,2])
<matplotlib.collections.PathCollection object at 0x000002C27F0614E0>
>>> plt.show()

输出效果如下。散点图使用datingDataMat矩阵的第二、第三列数据,分别表示特征值“玩视频游戏所耗时间百分比”和“每周所消费冰淇淋公升数”
在这里插入图片描述
由于没有使用样本分类的特征值,我们很难从图上看到任何有用的数据模式信息。一般来说,我们会采用色彩或其他的记号来标记不同样本分类。

emmmm,我的geany出现了点问题,乖乖去下载anaconda了。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值