算法学习2:KNN 算法

昨天找到一个数据分析的众包网站(kaggle),希望借此来练习一下前段时间学习到的ML算法。

今天就来回顾一下之前学习到的 KNN 算法,并用KNN算法进行手写数字的识别。


KNN 算法_手写识别实例

1.算法介绍: 

   kNN算法,即K最近邻(k-NearestNeighbor)分类算法,是最简单的机器学习算法之一,算法思想很简单:从训练样本集中选择k个与测试样本“距离”最近的样本,这k个样本中出现频率最高的类别即作为测试样本的类别。


优点:精度高、对异常值不敏感、无数据输入假定

缺点:计算复杂度高、空间复杂度高

适用数据范围:数值型、标称型

                                                                                                                                                    

K-近邻算法的一般步骤:

1.数据收集:可以使用任何方法

2.准本数据:距离计算所需要的数值,最好是结构化的数据格式

3.分析数据:可以使用任何方法

4.训练算法:此步骤不适用于K-近邻算法

5.测试算法:计算错误率

6.使用算法:首先需要输入样本数据和结构化的输出结果,然后运行K-近邻算法判定输入数据分别属于哪一分类,最后应用对计算出的分类执行后续的处理

                                                                                                                                                    

分类过程如下:

1.确定K值(K值是指对于一个待分类的数据点,我们要寻找K个它的邻居,即训练样品中与它距离最近的K个数据点)   K的取值一般不大于20(《机器学习实战》)

2.根据事先确定的距离度量公式(如:欧式距离等),得到待分类数据点和所有训练样品(已知类别的样品点)中距离最近的K个样品

3.统计这K个样品点中各个类别的数量。选取K个样品点中所属类别数量最多的类别作为待分类样品点的类别。


2.算法代码与实践:

从kaggle 网站的 digit-recognizer 项目中下载数据,所下载的数据分别为train.csv 和test.csv 两个数据文件。
本文代码采用python 编写, 会用到python 的 csv库、numpy库 ,需要用到各种库的相关内容稍后解析。

KNN算法的核心函数:
classify0(inx,dataSet,labels,k)
inx:待分类的数据点
dataSet:所以训练样品的集合
labels:训练样品的类别集合
返回:待分类的数据点的K个邻居类别最多的一个类别

<span style="font-size:14px;">def classify0(inx,dataSet,labels,k):
	# """kNN algorithm:
	# 1. 计算已知类别数据集中的点与当前点之间的距离
	# 2. 按照距离递增次序排序
	# 3. 选取与当前点距离最小的k个点
	# 4. 确定前k个点所在类别的出现频率
	# 5. 返回前k个点出现频率最高的类别作为当前点的预测分类"""
	dataSetSize = dataSet.shape[0]   #返回矩阵的行数和列数
	diffMat = tile(inx ,(dataSetSize,1))-dataSet   #tile :复制函数,返回一个list
	sqDiffMat = diffMat ** 2
	sqDistances = sqDiffMat.sum(axis = 1)
	distances = sqDistances **0.5
	sortedDistIndicies = distances.argsort() 
	classCount = {}
	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]</span>

获取训练用的数据:
gettrainData(filename)
filename :所下载的train.csv文件
返回:训练数据集合和训练数据的类别集合

<span style="font-size:14px;">def gettrainData(filename):
	"""获取训练用的数据 """
	datas = []
	labels = []
	with open(filename,'rb') as myfile:
		lines = csv.reader(myfile)
		lines.next()
		for line in lines:
			data = []
			for n,num in enumerate(line):
				data.append(int(num))
			datas.append(data)
	for data in datas:
		labels.append(data[0])
		del data[0]
	datas = array(datas)
	print 'get traindata ok'
	return datas,labels</span>

获取测试用的数据:
gettestData(filename)
filename :所下载的test.csv文件
返回:测试数据集合

<span style="font-size:14px;">def gettestData(filename):
	"""获取测试用的数据"""
	datas = []
	with open(filename,'rb') as myfile:
		lines = csv.reader(myfile)
		lines.next()
		for line in lines:
			data = []
			for n,num in enumerate(line):
				data.append(int(num))
			datas.append(data)
	datas = array(datas)
	print 'get testdata ok'
	return datas</span>

用训练数据进行算法验证:
testKNN0(filename,trainRate,k)
filename :所下载的train.csv文件
trainRate:取训练数据中,进行训练的数据量与所有训练数据的比值

返回:按trianRate 的比例去预测,KNN算法预测与真实情况相比较的准确度。调整trainRate 会得到不同的准确度

<span style="font-size:14px;">def testKNN0(filename,trainRate,k):
	"""对KNN算法进行测试  从训练数据中截取一部分进行训练,另一部分进行测试,检测正确率"""
	datalist,datalabels = gettrainData(filename)
	# datalist = autpNorm(datalist)
	count = len(datalist)
	trainNum = int(count*trainRate)
	trainData,trainlabels = datalist[0:int(trainNum)],datalabels[0:int(trainNum)]
	testCorrectRate = 0.0
	for i in range(trainNum,count):
		idx = classify0(datalist[i],trainData,trainlabels,k)
		print i - trainNum
		if idx == datalabels[i]:
			# print '预测的类别为:'.decode('utf-8').encode('gbk'),idx,"实际类别为:".decode('utf-8').encode('gbk'),datalabels[i],'right'
			testCorrectRate = testCorrectRate + 1
		else:
			pass
			# print '预测的类别为:'.decode('utf-8').encode('gbk'),idx,"实际类别为:".decode('utf-8').encode('gbk'),datalabels[i]
	testCorrectRate = testCorrectRate/(count - trainNum )
	return testCorrectRate</span>









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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值