机器学习实战(一)--K近邻算法实现

本文为参考<<Machine Learning in Action>>所写成。

1.原理:不再赘述

2.k近邻算法的一般流程

(1)收集数据

(2)准备数据:最好是结构化的数据格式

(3)分析数据

(4)训练算法:注意!该步骤不适用于k近邻算法。(注:k近邻是基于实例的算法,不需要训练)

(5)测试算法:计算错误率

(6)使用算法

3.具体实现

3.1准备:使用python导入数据

首先,创建名为knn.py的python模块。在这一部分,编写一个导入数据的通用函数。如下:

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

3.2实施knn算法

这一部分实现的功能为使用knn算法进行分类,伪代码如下:

对未知类别属性的数据集中的每个点依次执行以下操作:

(1)计算已知类别数据集中的点与当前点之间的距离

(2)按照距离递增次序排序

(3)选取与当前点距离最小的k个点

(4)确定前k个点所在类别的出现频率

(5)返回前k个点出现频率最高的类别作为当前点的预测分类。

基于上述伪代码实现的分类算法如下:

'''
@abstract:knn的分类函数
@input: inX为用于分类的输入向量;dataSet为输入的训练样本集;
		labels为标签向量;k为knn中的k
@output:inX对应的类别标签
'''
def classify0(inX, dataSet, labels, k):
	#shape是numpy.core.fromnumeric中的函数,其功能是读取矩阵的长度
	#其输入可以是一个整数,代表维度,如下即为计算矩阵第一维的长度
	#也可以是一个矩阵,返回则为该元组的长度的元组
	dataSetSize = dataSet.shape[0]  #dataSet第一维的长度与labels长度相同
	#tile是numpy.lib.shape_base中的函数,其功能是重复某个数组
	#tile(a,(b,c))参数:a是要重复的数组,b是重复的维度,c是对每个维度再出现的次数
	#如下的功能是将inX重复生成[dataSetSize,len(inX)]的二维矩阵
	diffMat = tile(inX, (dataSetSize,1)) - dataSet
	sqDiffMat = diffMat**2    #矩阵每个位置单独平方
	#矩阵内部求和,axis内为求和基准(axis=0则为按列求和,axis=1则为按行求和)
	sqDistances = sqDiffMat.sum(axis=1)
	distances = sqDistances**0.5   #矩阵每个位置单独开方
	#以上,距离计算完成,使用的是欧氏距离
	sortedDistIndices = distances.argsort()   #排序,返回的是由小到大的序号
	classCount = {}
	for i in range(k):  #选取
		voteIlabel = labels[sortedDistIndices[i]]
		classCount[voteIlabel] = classCount.get(voteIlabel,0)+1
	#类别投票数目排序,选取最高得票的类别
	sortedClassCount = sorted(classCount.iteritems(),
					key=operator.itemgetter(1),reverse=True)
	return sortedClassCount[0][0]

3.3测试分类器

分类器的错误率----分类器给出错误结果的次数除以测试执行的总数。错误率是常用的评估方法,主要用于评估分类器在某个数据集上的执行效果。

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

4.1准备数据:从文本中解析数据

datingTestSet.txt,每一行包含【每年获得的飞行常客里程数,玩视频游戏所耗时间百分比,每周消费的冰淇淋公升数】,共1000行。接下来在knn.py中创建一个函数来处理输入格式问题。代码如下:

'''
@abstract: 读取文件,并整理成所需(矩阵)格式
@input: filename为要读取的文件名;num为训练数据的属性个数
'''
def file2matrix(filename,num=3):
	fr = open(filename)
	arrayOLines = fr.readlines()
	#得到文件行数
	numberOfLines = len(arrayOLines)
	#创建返回的numpy矩阵
	returnMat = zeros((numberOfLines,num)) #numberOfLines个长度为3的全零矩阵
	classLabelVector = []
	index = 0
	for line in arrayOLines:
		line = line.strip()
		listFromLine = line.split('\t')
		returnMat[index,:] = listFromLine[0:num] #第index行
		classLabelVector.append(int(listFromLine[-1]))
		index += 1
	return returnMat, classLabelVector
4.2分析数据:使用matplotlib创建散点图

直接浏览文本文件的方式并不友好,一般会采用图形化的方式直观的展现数据。

'''
@abstract:使用matplotlib绘制散点图
@input:filename文件名;i为文件的第i列作为横轴,j为文件的第j列作为纵轴
@output:散点图
'''
def draw_scatter(filename='datingTestSet.txt', i=1, j=2):
	fig = plt.figure()
	ax = fig.add_subplot(111)
	datingDataMat,datingLabels = file2matrix(filename)
	ax.scatter(datingDataMat[:,i],datingDataMat[:,j],
			15.0*array(datingLabels),15.0*array(datingLabels))
	plt.show()


绘制结果如下图所示,图中点的大小及颜色受类别影响。


4.3准备数据:归一化数值
采用min-max归一化对维度进行去量纲,对应的在knn.py中增加一个autoNorm()函数。

'''
@abstract:对数据进行min-max归一化
@input:dataSet为需要归一化的数据集,矩阵格式
'''
def autoNorm(dataSet):
	#numpy中的min(0)/max(0)函数相应的为求每一列的最小/大值
	#min(1)/max(1)则为每一行 返回值均为数组
	minVals = dataSet.min(0)
	maxVals = dataSet.max(0)
	ranges = maxVals-minVals
	normDataSet = zeros(shape(dataSet))
	m = dataSet.shape[0]
	normDataSet = dataSet-tile(minVals,(m,1))
	#numpy中"/"代表的具体的特征值相除,矩阵除法的用法为linalg.solve(matA,matB)
	normDataSet = normDataSet/tile(ranges,(m,1))
	return normDataSet, ranges, minVals
4.4测试算法
分类器正确率是十分重要的,最简单直接的测试方法是 随机分出一部分数据来做测试。

'''
@abstract:测试算法准确率的方法
@input: hoRatio为用于测试的数据的比例
@output: 错误率(输出结果不一致的数目/总测试数目)
'''
def datingClassTest(hoRatio=0.10):
	datingDataMat, datingLabels = file2matrix('datingTestSet.txt')
	normMat, ranges, minVals = autoNorm(datingDataMat)
	m = normMat.shape[0]
	numTestVecs = int(m*hoRatio) #用于测试的样本数,前百分之十
	errorCount = 0.0
	for i in range(numTestVecs):
		#knn是基于实例的方法,不需要训练。
		classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],
							datingLabels[numTestVecs:m],3)
		print "the classifier came back with: %d,the real anwser is: %d"\
				% (classifierResult, datingLabels[i])
		if (classifierResult != datingLabels[i]): errorCount += 1.0
	print "the total errorRate is: %f" % (errorCount/float(numTestVecs))
注:以上为参考<<机器学习实战>>一书第二章k近邻算法,第二节【使用k近邻算法改进约会网站的配对效果】所写成。完整代码 [knn.py]已上传。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值