机器学习算法学习01——k-近邻算法及手写数字识别系统

文章目录

  • 一、kNN算法概述
  • 二、算法原理
  • 三、相关代码
    • 1.准备:使用Python导入数据
    • 2.从文本文件中解析数据
    • 3.预测类别
  • 四、手写数字识别系统实验
    • 1. 实验概述
    • 2.实验内容
    • 3.代码
    • 3.1 准备数据:将图像转换为测试向量
    • 3.2 测试kNN算法
  • 总结


一、kNN算法概述

1.k邻近算法直译为K个最近的邻居,是一种聚类算法。采用测量不同特征值之间的距离方法进行分类。基于大量数据的基础上,做出相应的预测,一般运用于手写数字识别,约会网站的大量数据匹配等等。

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

3.缺点:计算复杂度高,空间复杂度高。

4.适用数据范围是:数值型和标称型。

二、算法原理

以《机器学习实战》第二章导言为例我们需要鉴别某个电影的类别,我们通过比对发现他和我们列举的中5个电影相似,我们发现这5个镜头其中4个是打斗,1个是接吻,所以判定这部电影是武打片。这就是一个5NN算法。

总结出他的流程:
输入:数据x 已知类别的样本z
输出:x的类别y

1.计算数据x与z中每个样本的距离d

2.利用距离d获取与x距离前K小的索引index

3.利用index从样本z中选取出k个样本

4.统计这k个样本的类别,类别数统计最多的作为x的类别
机器学习算法学习01——k-近邻算法及手写数字识别系统_第1张图片

三、相关代码

1.准备:使用Python导入数据

导入两个模块,一个是科学计算包NumPy,还一个是运算符模块。定义createDataSet函数,使用该函数创建数据集和标签。
这里有4组数据,每组数据有两个我们已知的属性或特征值,向量labels包含了每个数据点的标签信息,labels包含的元素个数等于group矩阵行数。

from numpy import  *  #导入科学计算包Numpy
import  operator      #导入运算符模块

def createDataSet():
    group=array([[3,104],[2,100],[101,10],[99,5]])  #导入四部电影[打斗镜头次数,接吻镜头]
    labels=['A','A','B','B']    #labels分类标签,A为爱情片,B为接吻镜头
    return group,labels

2.从文本文件中解析数据

伪代码:对未知类别属性的数据集中的每个点依次执行以下操作
(1)计算已知类别数据集中的点与当前点之间的距离;
(2)按照距离递增次序排序;
(3)选取与当前点距离最小的k个点;
(4)确定前k个点所在类别的出现频率;
(5)返回前k个点出现频率最高的类别作为当前点的预测分类。


def classify0(intX,dataSet,labels,k): 
  	dataSetSize=dataSet.shape[0]    
    diffMat=tile(intX,(dataSetSize,1))-dataSet   
    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.items(),key=operator.itemgetter(1),reverse=True)    
    return sortedClassCount[0][0] 

classify0 ()函数有4个输入参数:用于分类的输入向量是inX,dataSet输入的训练样本集,labels标签向量,k用于选择最近邻居的数目。其中标签向量的元素数目和矩阵dataSet的行数相同。程序所使用的欧氏距离公式,计算两个向量点xA和xB之间的距离:
在这里插入图片描述
计算完所有点之间的距离后,可以对数据按照从小到大的次序排序。然后,确定前k个距离最小元素所在的主要分类,输入k总是正整数;最后,将classCount字典分解为元组列表,然后使用程序第二行导入运算符模块的itemgetter方法,按照第二个元素的次序对元组进行排序。此处的排序是逆序,即按照从最大到最小次序排序,最后返回发生频率最高的元素标签

3.预测类别

group,labels = createDataSet()
print(classify0([18,90],group,labels,3))

预测结果为A:爱情片。

A

若是训练数据集过大,每次都需要计算数据的距离值,实际耗时会过大,不仅时间开销大,存储空间的消耗也巨大。

四、手写数字识别系统实验

1. 实验概述

构造一个能识别数字0到9的基于kNN分类器的手写数字识别系统。
需要识别的数字已经使用图形处理软件,处理成具有相同的色彩和大小:宽高是32像素✖32像素的黑白图像。

2.实验内容

(1) 使用K-NN算法识别数字0-9,实现最基本的KNN算法,使用trainingDigits文件夹下的数据,对testDigits中的数据进行预测。
(2)改变K的值,并观察对正确率的影响。

3.代码

3.1 准备数据:将图像转换为测试向量

def img2vector(filename):
    return_vector = zeros((1, 1024))
    fr = open(filename)
    for i in range(32):
        lineStr = fr.readline()
        for j in range(32): 
            return_vector[0, 32 * i + j] = int(lineStr[j])
    return return_vector

3.2 测试kNN算法

def handwritingClassTest():
    hwLabels = []
    trainingFileList = listdir('D:/study/机器学习/py code/kNN/trainingDigits')
    m = len(trainingFileList)
    trainingMat = zeros((m,1024))
    for i in range(m):
        fileNameStr = trainingFileList[i]
        fileStr = fileNameStr.split('.')[0]
        #9
        classNumStr = int(fileStr.split('_')[0])
        hwLabels.append(classNumStr)
        trainingMat[i,:] = img2vector('D:/study/机器学习/py code/kNN/trainingDigits/%s' % fileNameStr)
    #测试集
    testFileList = listdir('D:/study/机器学习/py code/kNN/testDigits')  
    errorCount = 0.0
    mTest = len(testFileList)    
    for i in range(mTest):
        fileNameStr = testFileList[i]
        fileStr = fileNameStr.split('.')[0]
        classNumStr = int(fileStr.split('_')[0])
        #1*1024的列表
        vectorUnderTest = img2vector('D:/study/机器学习/py code/kNN/testDigits/%s' % fileNameStr)
        classifierResult = classify0(vectorUnderTest,trainingMat,hwLabels,3)
        print("预测值: ",classifierResult)
        print("真实值: ",classNumStr)
        if(classifierResult!=classNumStr):
            errorCount += 1.0
    print("总共错误的数量为: ",errorCount)
    print("错误率为: ",(errorCount)/float(mTest))

预测结果为:

...
预测值:  9
真实值:  9
预测值:  9
真实值:  9
总共错误的数量为:  10.0
错误率为:  0.010570824524312896

总结

1.在本次实验中,我完成了理解了KNN算法,是分类数据最简单有效的算法,但是如果训练数据集很大,存储空间就必须够大,并且算法的执行效率不高。正如手写数字识别系统这个案例,维度高、样本多,计算过程就十分繁琐,不太适合。
2.我了解了传统机器学习算法,为后序深度学习打牢基础。

你可能感兴趣的:(机器学习,python,算法)