KNN分类算法案例:手写数字图片识别代码实现及测试

1 需求

利用一个手写数字“先验数据”集,使用knn算法来实现对手写数字的自动识别;

先验数据(训练数据)集:

²数据维度比较大,样本数比较多。

²数据集包括数字0-9的手写体。

²每个数字大约有200个样本。

²每个样本保持在一个txt文件中。

²手写体图像本身的大小是32x32的二值图,转换到txt文件保存后,内容是32x32个数字,0或者1,如下:

KNN分类算法案例:手写数字图片识别代码实现及测试_第1张图片

数据集压缩包解压后有两个目录:

²目录trainingDigits存放的是大约2000个训练数据

²目录testDigits存放大约900个测试数据。

2 模型分析

本案例看起来跟前一个案例几乎风马牛不相及,但是一样可以用KNN算法来实现。没错,这就是机器学习的魅力,不过,也是机器学习的难点:模型抽象能力!

思考:

1、手写体因为每个人,甚至每次写的字都不会完全精确一致,所以,识别手写体的关键是“相似度”

2、既然是要求样本之间的相似度,那么,首先需要将样本进行抽象,将每个样本变成一系列特征数据(即特征向量)

3、手写体在直观上就是一个个的图片,而图片是由上述图示中的像素点来描述的,样本的相似度其实就是像素的位置和颜色之间的组合的相似度

4、因此,将图片的像素按照固定顺序读取到一个个的向量中,即可很好地表示手写体样本

5、抽象出了样本向量,及相似度计算模型,即可应用KNN来实现

3 python实现

新建一个kNN.py脚本文件,文件里面包含四个函数:

1)一个用来生成将每个样本的txt文件转换为对应的一个向量,

2)一个用来加载整个数据集,

3)一个实现kNN分类算法。

4)最后就是实现加载、测试的函数。

#########################################

# kNN: k Nearest Neighbors

# 参数:        inX: vector to compare to existing dataset (1xN)

#             dataSet: size m data set of known vectors (NxM)

#             labels: data set labels (1xM vector)

#             k: number of neighbors to use for comparison

            

# 输出:     多数类

#########################################

from numpy import *

import operator

import os

# KNN分类核心方法

def kNNClassify(newInput, dataSet, labels, k):

numSamples = dataSet.shape[0]  # shape[0]代表行数

## step 1: 计算欧式距离

# tile(A, reps): 将A重复reps次来构造一个矩阵

# the following copy numSamples rows for dataSet

diff = tile(newInput, (numSamples, 1)) - dataSet  # Subtract element-wise

squaredDiff = diff ** 2 # squared for the subtract

squaredDist = sum(squaredDiff, axis = 1)  # sum is performed by row

distance = squaredDist ** 0.5

## step 2: 对距离排序

# argsort()返回排序后的索引

sortedDistIndices = argsort(distance)

classCount = {}  # 定义一个空的字典

for i in xrange(k):

## step 3: 选择k个最小距离

voteLabel = labels[sortedDistIndices[i]]

## step 4: 计算类别的出现次数

# when the key voteLabel is not in dictionary classCount, get()

# will return 0

classCount[voteLabel] = classCount.get(voteLabel, 0) + 1

## step 5: 返回出现次数最多的类别作为分类结果

maxCount = 0

for key, value in classCount.items():

if value > maxCount:

maxCount = value

maxIndex = key

return maxIndex

# 将图片转换为向量

def  img2vector(filename):

  rows = 32

  cols = 32

  imgVector = zeros((1, rows * cols))

  fileIn = open(filename)

  for row in xrange(rows):

  lineStr = fileIn.readline()

  for col in xrange(cols):

  imgVector[0, row * 32 + col] = int(lineStr[col])

  return imgVector

# 加载数据集

def loadDataSet():

## step 1: 读取训练数据集

print "---Getting training set..."

dataSetDir = 'E:/Python/ml/knn/'

trainingFileList = os.listdir(dataSetDir + 'trainingDigits')  # 加载测试数据

numSamples = len(trainingFileList)

train_x = zeros((numSamples, 1024))

train_y = []

for i in xrange(numSamples):

filename = trainingFileList[i]

# get train_x

train_x[i, :] = img2vector(dataSetDir + 'trainingDigits/%s' % filename)

# get label from file name such as "1_18.txt"

label = int(filename.split('_')[0]) # return 1

train_y.append(label)

## step 2:读取测试数据集

print "---Getting testing set..."

testingFileList = os.listdir(dataSetDir + 'testDigits') # load the testing set

numSamples = len(testingFileList)

test_x = zeros((numSamples, 1024))

test_y = []

for i in xrange(numSamples):

filename = testingFileList[i]

# get train_x

test_x[i, :] = img2vector(dataSetDir + 'testDigits/%s' % filename)

# get label from file name such as "1_18.txt"

label = int(filename.split('_')[0]) # return 1

test_y.append(label)

return train_x, train_y, test_x, test_y

# 手写识别主流程

def testHandWritingClass():

## step 1: 加载数据

print "step 1: load data..."

train_x, train_y, test_x, test_y = loadDataSet()

## step 2: 模型训练.

print "step 2: training..."

pass

## step 3: 测试

print "step 3: testing..."

numTestSamples = test_x.shape[0]

matchCount = 0

for i in xrange(numTestSamples):

predict = kNNClassify(test_x[i], train_x, train_y, 3)

if predict == test_y[i]:

matchCount += 1

accuracy = float(matchCount) / numTestSamples

## step 4: 输出结果

print "step 4: show the result..."

print 'The classify accuracy is: %.2f%%' % (accuracy * 100)

测试非常简单,只需要在命令行中输入:

import kNN

kNN.testHandWritingClass()

输出结果如下:

step 1: load data...

---Getting training set...

---Getting testing set...

step 2: training...

step 3: testing...

step 4: show the result...

The classify accuracy is: 98.84%

你可能感兴趣的:(人工智能)