机器学习实战_K近邻算法 ——手写数字预测(sklearn api)

一、序

机器学习实战_K近邻算法 ——手写数字预测 调用的是自己编写的分类器classify0,主要是为了学习理论原理;在实际是项目中通常调用工具包的api接口,比如sklearn,这也体现了python的一个便利性,不用总是自己造轮子。虽然python提供了很多机器学习的工具包,但是也是在我们了解和熟悉算法的基本实现原理。

二、sklearn中KNeighborsClassifier的介绍

class sklearn.neighbors.KNeighborsClassifier(n_neighbors=5, weights=‘uniform’, algorithm=‘auto’, leaf_size=30, p=2, metric=‘minkowski’, metric_params=None, n_jobs=None, **kwargs)

官方api文档:KNeighborsClassifier

1、KNeighborsClassifier的参数(官方文译):

n_neighbors: int, 可选参数(默认为 5)
  用于kneighbors查询的默认邻居的数量

weights(权重): str or callable(自定义类型), 可选参数(默认为 ‘uniform’)
  用于预测的权重函数。可选参数如下:

  • ‘uniform’ : 统一的权重. 在每一个邻居区域里的点的权重都是一样的。
  • ‘distance’ : 权重点等于他们距离的倒数。使用此函数,更近的邻居对于所预测的点的影响更大。
  • [callable] : 一个用户自定义的方法,此方法接收一个距离的数组,然后返回一个相同形状并且包含权重的数组。

algorithm(算法): {‘auto’, ‘ball_tree’, ‘kd_tree’, ‘brute’}, 可选参数(默认为 ‘auto’)
  计算最近邻居用的算法:

  • ‘ball_tree’ 使用算法BallTree
  • ‘kd_tree’ 使用算法KDTree
  • ‘brute’ 使用暴力搜索.
  • ‘auto’ 会基于传入fit方法的内容,选择最合适的算法。

  注意 : 如果传入fit方法的输入是稀疏的,将会重载参数设置,直接使用暴力搜索。

leaf_size(叶子数量): int, 可选参数(默认为 30)
  传入BallTree或者KDTree算法的叶子数量。此参数会影响构建、查询BallTree或者KDTree的速度,以及存储BallTree或者KDTree所需要的内存大小。 此可选参数根据是否是问题所需选择性使用。

p: integer, 可选参数(默认为 2)
  用于Minkowski metric(闵可夫斯基空间)的超参数。p = 1, 相当于使用曼哈顿距离 (l1),p = 2, 相当于使用欧几里得距离(l2) 对于任何 p ,使用的是闵可夫斯基空间(l_p)

metric(矩阵): string or callable, 默认为 ‘minkowski’
  用于树的距离矩阵。默认为闵可夫斯基空间,如果和p=2一块使用相当于使用标准欧几里得矩阵. 所有可用的矩阵列表请查询 DistanceMetric 的文档。

metric_params(矩阵参数): dict, 可选参数(默认为 None)
  给矩阵方法使用的其他的关键词参数。

n_jobs: int, 可选参数(默认为 1)
  用于搜索邻居的,可并行运行的任务数量。如果为-1, 任务数量设置为CPU核的数量。不会影响fit方法。

2、 KNeighborsClassifier的方法(官方文译)

方法名含义
fit(X, y)使用X作为训练数据,y作为目标值(类似于标签)来拟合模型。
get_params([deep])获取估值器的参数。
kneighbors([X, n_neighbors, return_distance])查找一个或几个点的K个邻居。
kneighbors_graph([X, n_neighbors, mode])计算在X数组中每个点的k邻居的(权重)图。
predict(X)给提供的数据预测对应的标签。
predict_proba(X)返回测试数据X的概率估值。
score(X, y[, sample_weight])返回给定测试数据和标签的平均准确值。
set_params(**params)设置估值器的参数。

三、手写数字预测(sklearn api)

1、修改内容

  • 1)、增加的代码
    # 构造kNN分类器
    knn = KNeighborsClassifier(n_neighbors=3, algorithm='auto')
    # 拟合模型,trainingMat为测试矩阵,hwLabels为对应标签
    knn.fit(trainingMat, hwLabels)
  • 2)、替换的内容
       # 获得预测结果
       classifierResult = knn.predict(vectorUnderTest)         # 替换 classifierResult = classify0(vectorUnderTest) 

2、代码


import numpy as np
from os import listdir

from sklearn.neighbors import KNeighborsClassifier


def img2vector(filename):
    """
    函数说明:将32*32的二进制图像转换为1*1024向量

    Parameters:
        filename - 文件名

    Returns:
        returnVect - 返回二进制图像的1*1024向量

    """
    # 创建1*1024零向量
    returnVect = np.zeros((1, 1024))

    with open(filename) as fr:
        # 按行读取
        for i in range(32):
            # 读取一行数据
            lineStr = fr.readline()
            # 每一行的前32个数据依次存储到returnVect中
            for j in range(32):
                returnVect[0, 32 * i + j] = int(lineStr[j])
        # 返回转换后的1*1024向量
    return returnVect


def handwritingClassTest():
    """
    函数说明:手写数字分类测试

    Parameters:
        None

    Returns:
        None
    """
    # 测试集的Labels
    hwLabels = []

    # 返回trainingDigits目录下的文件名
    trainingFileList = listdir('trainingDigits')
    # 返回文件夹下文件的个数
    m = len(trainingFileList)
    # 初始化训练的Mat矩阵(全零阵),测试集
    trainingMat = np.zeros((m, 1024))
    # 从文件名中解析出训练集的类别
    for i in range(m):
        # 获得文件的名字
        fileNameStr = trainingFileList[i]
        # 获得分类的数字
        classNumStr = int(fileNameStr.split('_')[0])
        # 将获得的类别添加到hwLabels中
        hwLabels.append(classNumStr)
        # 将每一个文件的1x1024数据存储到trainingMat矩阵中
        trainingMat[i,:] = img2vector('trainingDigits/%s' % fileNameStr)

    # 构造kNN分类器
    knn = KNeighborsClassifier(n_neighbors=3, algorithm='auto')
    # 拟合模型,trainingMat为测试矩阵,hwLabels为对应标签
    knn.fit(trainingMat, hwLabels)

    # 返回testDigits目录下的文件列表
    testFileList = listdir('testDigits')
    # 错误检测计数
    errorCount = 0.0
    # 测试数据的数量
    mTest = len(testFileList)
    # 从文件中解析出测试集的类别并进行分类测试
    for i in range(mTest):
        # 获得文件名字
        fileNameStr = testFileList[i]
        # 获得分类的数字
        classNumStr = int(fileNameStr.split('_')[0])
        vectorUnderTest = img2vector('testDigits/%s' % fileNameStr)
        # 获得预测结果
        classifierResult = knn.predict(vectorUnderTest)
        print("分类返回结果为%d\t真实结果为%d" % (classifierResult, classNumStr))
        if classifierResult != classNumStr:
            errorCount += 1.0
    print("总共错了%d个数据\n错误率为%f%%" % (errorCount, errorCount / mTest * 100))


if __name__ == '__main__':

    handwritingClassTest()


四、运行结果

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值