机器学习实战kNN之手写识别

来源:互联网 发布:python 命令行 参数 编辑:程序博客网 时间:2024/05/12 12:02

欢迎关注我的个人博客blog.timene.com

kNN算法算是机器学习入门级绝佳的素材。书上是这样诠释的:“存在一个样本数据集合,也称作训练样本集,并且样本集中每个数据都有标签,即我们知道样本集中每一条数据与所属分类的对应关系。输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应的特征比较,算法提取样本集中特征最相似数据(最近邻)的分类标签。一般来说,我们只选择样本数据集中前K个最相似的数据,这就是k-近邻算法中k的出处,通常k是不大于20的整数。最后,选择k个最相似数据中出现次数最多的分类,作为新数据的分类”。

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

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

适用数据范围:数值型或标称型。

算法的python实现:

def kNN(data, dataSet, dataLabel, k=3, similarity=sim_distance):  scores = [(sim_distance(data, dataSet[i]), dataLabel[i]) for i in range(len(dataSet))]sortedScore = sorted(scores, key=lambda d: d[0], reverse=False) scores = sortedScore[0:k]classCount = {} for score in scores:classCount[score[1]] = classCount.get(score[1], 0) + 1sortedClassCount = sorted(classCount.items(), key=lambda d: d[1], reverse=True)return sortedClassCount[0][0]

下面分为几步骤来学习这个算法:

(1)准备数据

(2)测试算法

先介绍一个这个手写识别系统,简单起见,该系统只能识别数字0---9,需要识别的数字已经使用图形处理软件,处理成具有相同色彩和大小:32*32像素的黑白照片。目录trainingDigits中包含了大约2000个训练样本,目录testDigits中大约有900个测试样本。

第一步,准备数据:将图片数据转换成测试向量。这一步就是把我们32*32的二进制图像矩阵转换成1*1024的向量。

def img2vector(filename):vec = []file = open(filename)for i in range(32):line = file.readline()for j in range(32):vec.append(int(line[j]))return vec

第二步,测试算法准确率,我们用trainingDigits目录下的样本做训练,来测试testDigits目录下的样本,来计算准确率。

def test():trainData, trainLabel = [], []trainFileList = os.listdir('digits/trainingDigits/')for filename in trainFileList:trainData.append(img2vector('digits/trainingDigits/%s' % filename))trainLabel.append(int(filename.split('_')[0]))succCnt, failCnt = 0, 0testFileList = os.listdir('digits/testDigits')for filename in testFileList:data = img2vector('digits/testDigits/%s' % filename)num = kNN(data, trainData, trainLabel)if num == int(filename.split('_')[0]):succCnt += 1print 'succ'else:failCnt += 1print 'fail'print "error rate is : %f " % (failCnt/float(failCnt+succCnt))

我这里测试,K取默认值3,错误率是0.013742,


不会上传文件,所以把代码贴在下面,测试数据在http://download.csdn.net/detail/wyb_009/5649337第二章下面

import os, mathdef sim_distance(a, b):sum_of_squares = sum([pow(a[i]-b[i], 2) for i in range(len(a))])  return sum_of_squares def kNN(data, dataSet, dataLabel, k=3, similarity=sim_distance):  scores = [(sim_distance(data, dataSet[i]), dataLabel[i]) for i in range(len(dataSet))]sortedScore = sorted(scores, key=lambda d: d[0], reverse=False) scores = sortedScore[0:k]classCount = {} for score in scores:classCount[score[1]] = classCount.get(score[1], 0) + 1sortedClassCount = sorted(classCount.items(), key=lambda d: d[1], reverse=True)return sortedClassCount[0][0]def img2vector(filename):vec = []file = open(filename)for i in range(32):line = file.readline()for j in range(32):vec.append(int(line[j]))return vecdef test():trainData, trainLabel = [], []trainFileList = os.listdir('digits/trainingDigits/')for filename in trainFileList:trainData.append(img2vector('digits/trainingDigits/%s' % filename))trainLabel.append(int(filename.split('_')[0]))print "load train data ok"succCnt, failCnt = 0, 0testFileList = os.listdir('digits/testDigits')for filename in testFileList:data = img2vector('digits/testDigits/%s' % filename)num = kNN(data, trainData, trainLabel)if num == int(filename.split('_')[0]):succCnt += 1print 'succ'else:failCnt += 1print 'fail: kNN get %ld, real is %ls' %(num, int(filename.split('_')[0]))print "error rate is : %f " % (failCnt/float(failCnt+succCnt))if __name__ == "__main__":test()







原创粉丝点击