12 机器学习 - KNN实现手写数字识别

简介: 12 机器学习 - KNN实现手写数字识别

需求

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

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

  • 数据维度比较大,样本数比较多。
  • 数据集包括数字0-9的手写体。
  • 每个数字大约有200个样本。
  • 每个样本保持在一个txt文件中。
  • 手写体图像本身的大小是32x32的二值图,转换到txt文件保存后,内容也是32x32个数字,0或者1,如下:

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

  • 目录trainingDigits存放的是大约2000个训练数据
  • 目录testDigits存放大约900个测试数据。

模型分析

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

思考:

1. 手写体因为每个人,甚至每次写的字都不会完全精确一致,所以,识别手写体的关键是“相似度”
2. 既然是要求样本之间的相似度,那么,首先需要将样本进行抽象,将每个样本变成一系列特征数据(即特征向量)
3. 手写体在直观上就是一个个的图片,而图片是由上述图示中的像素点来描述的,样本的相似度其实就是像素的位置和颜色之间的组合的相似度
4. 因此,将图片的像素按照固定顺序读取到一个个的向量中,即可很好地表示手写体样本
5. 抽象出了样本向量,及相似度计算模型,即可应用KNN来实现

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%
目录
相关文章
|
5月前
|
机器学习/深度学习 算法
【阿旭机器学习实战】【30】二手车价格预估--KNN回归案例
【阿旭机器学习实战】【30】二手车价格预估--KNN回归案例
|
1月前
|
机器学习/深度学习 算法
机器学习入门(三):K近邻算法原理 | KNN算法原理
机器学习入门(三):K近邻算法原理 | KNN算法原理
|
1月前
|
机器学习/深度学习 算法 API
机器学习入门(五):KNN概述 | K 近邻算法 API,K值选择问题
机器学习入门(五):KNN概述 | K 近邻算法 API,K值选择问题
|
5月前
|
机器学习/深度学习 算法 搜索推荐
【机器学习】近邻类模型:KNN算法在数据科学中的实践与探索
【机器学习】近邻类模型:KNN算法在数据科学中的实践与探索
97 0
|
6月前
|
机器学习/深度学习 人工智能 算法
【机器学习】K-means和KNN算法有什么区别?
【5月更文挑战第11天】【机器学习】K-means和KNN算法有什么区别?
|
5月前
|
机器学习/深度学习 算法 数据处理
【阿旭机器学习实战】【33】中文文本分类之情感分析--朴素贝叶斯、KNN、逻辑回归
【阿旭机器学习实战】【33】中文文本分类之情感分析--朴素贝叶斯、KNN、逻辑回归
|
6月前
|
机器学习/深度学习 数据采集 存储
【机器学习】K-近邻算法(KNN)全面解析
K-近邻算法(K-Nearest Neighbors, KNN)是一种基于实例的学习方法,属于监督学习范畴。它的工作原理简单直观:给定一个训练数据集,对新的输入实例,KNN算法通过计算其与训练集中每个实例的距离,找出距离最近的K个邻居,然后根据这些邻居的类别(对于分类任务)或值(对于回归任务)来预测新实例的类别或值。KNN因其简单高效和无需训练过程的特点,在众多领域中得到广泛应用,如模式识别、推荐系统、图像分类等。
284 0
|
6月前
|
机器学习/深度学习 算法 Python
PYTHON银行机器学习:回归、随机森林、KNN近邻、决策树、高斯朴素贝叶斯、支持向量机SVM分析营销活动数据|数据分享(下)
PYTHON银行机器学习:回归、随机森林、KNN近邻、决策树、高斯朴素贝叶斯、支持向量机SVM分析营销活动数据|数据分享
|
6月前
|
机器学习/深度学习 算法 数据挖掘
PYTHON银行机器学习:回归、随机森林、KNN近邻、决策树、高斯朴素贝叶斯、支持向量机SVM分析营销活动数据|数据分享(上)
PYTHON银行机器学习:回归、随机森林、KNN近邻、决策树、高斯朴素贝叶斯、支持向量机SVM分析营销活动数据|数据分享
|
6月前
|
机器学习/深度学习 算法
机器学习—KNN算法
机器学习—KNN算法