KNN算法的Python实现并用于手写数字识别

一、原理和算法

K-近邻(k-Nearest Neighbor,KNN)是分类算法,是一个理论上比较成熟的方法,也是最简单的机器学习算法之一。该方法的思路是:如果一个样本在特征空间中的 k 个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。

算法思路:

1) 算距离:给定测试对象,计算它与训练集中的每个对象的距离

2) 找邻居:圈定距离最近的 k 个训练对象,作为测试对象的近邻

3) 做分类:根据这 k 个近邻归属的类别进行投票,对测试对象分类。

注意:如果选择较小的 K 值,训练实例集合就会变小,训练的近似误差会变的很小,训练数据与输入的新数据相近才能有效果。K 值变小的情况下,容易受到异常值的影响,更容易出现过拟合问题。 选择较大的 K 值,训练实例会变大,训练的近似误差亦会变的很大,如果训练数据与新输入的新数据不相关也会产生不同效果,容易出现样本均衡的问题,使模型变得简单,出现欠拟合问题。所以,K 值的选择是 KNN 算法的要点。

算法流程:

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

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

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

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

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

二、KNN的实现

import numpy as np
import random
from sklearn import preprocessing
from sklearn.decomposition import PCA
from sklearn.datasets import load_digits # 导入数据
import matplotlib.pyplot as plt
import pandas as pd


def knn(k, testdata, traindata, labels):
    #计算训练集的长度
    traindatasize = traindata.shape[0] 
    #将测试集扩展至训练集的长度,再求差值
    dif = np.tile(testdata,(traindatasize,1)) - traindata
    #求差值的平方
    sqrdif = dif**2 
    #求平方和
    sumsqrdif = sqrdif.sum(axis=1) 
    #再开根号,即所有的距离
    distance = sumsqrdif**0.5 
    #对距离进行排序,返回排序后的索引
    sorted_distance = distance.argsort() 
    #准备一个空字典,存放投票结果
    count = {}
    for i in range(0,k):  
        #提取索引多对应的标签值作为字典的key
        vote = labels[sorted_distance[i]]
        #票数作为字典的value
        count[vote] = count.get(vote,0)+1  
    #对最后的投票结果进行排序
    sorted_count = sorted(count.items(),key=lambda x:x[1],reverse=True) 
    #返回得票最多的标签
    return sorted_count[0][0] 

三、基于KNN的手写数字识别

数据集介绍:digits 数据集是 python 中 sklearn库中的一个手写数字数据集,该数据集包含1797个样本,每个样本包括8*8像素的图像和一个[0, 9]整数的标签。

digits 手写数据集部分图例如下图所示。

该数据集有 64 个特征值,也就是说有 64 个维度,用PCA把原始的64维数据降到18维。

以训练集:测试集=7:3的比例对digits数据集进行划分,通过设置随机数来随机选取样本,并设置随机数种子2,使我们的结果稳定不变,具有复现性。

# Load data
digits = load_digits()
data = digits.data
target = digits.target

#split dataset
number=[x for x in range(1797)]
random.seed(2)
random.shuffle(number)
number=number[:1258]
exnumber=[x for x in range(1797) if x not in number]
train_x=data[number]
train_y=target[number]
test_x=data[exnumber]
test_y=target[exnumber]

#PCA 
pca = PCA(n_components=18)
train_x = pca.fit_transform(train_x)
test_x = pca.transform(test_x)

# Test
result_y=np.zeros(test_x.shape[0])
for i in range(test_x.shape[0]):
    result_y[i]=knn(3, test_x[i], train_x, train_y)
correct_rate = np.mean(result_y == test_y)
print('Total correct rate: %.2f%%'% (correct_rate*100))

四、实验结果

下表列出了本文实现的 KNN 算法在 digits测试集上的预测结果。从表中可以看出,本文实现的 KNN 算法在digits测试集上识别总的准确率为 99.44%。在539条测试样本中,识别错误的总数是3。下表还详细列出了每类数字图像的准确率,除数字9外,其余数字的的识别准确率均高于平均值,准确率达到了100%;而数字9的识别准确率低于95%。

数字

类别

该类样本总数

识别错误总数

准确率

0

51

0

100%

1

55

0

100%

2

54

0

100%

3

58

0

100%

4

49

0

100%

5

59

0

100%

6

55

0

100%

7

50

0

100%

8

55

0

100%

9

53

3

94.34%

ALL

539

3

99.44%

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值