zoukankan      html  css  js  c++  java
  • 《机器学习实战》--KNN

    代码来自《机器学习实战》https://github.com/wzy6642/Machine-Learning-in-Action-Python3

    K-近邻算法(KNN)

    介绍

    简单地说,k-近邻算法采用测量不同特征值之间的距离方法进行分类。

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

    缺点:计算复杂度高、空间复杂度高,无法给出数据的内在含义。

    使用数据范围:数值型、标称型。

    分类函数的伪代码:

      对未知类别属性的数据集中的每个点依次执行以下操作:

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

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

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

      (4)确定前k个点所在类别的出现概率;

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

     1 """创建数据集
     2 返回: group - 数据集
     3      labels - 分类标签
     4 """
     5 def createDataSet():
     6     # 四组二维特征
     7     group = np.array([[1, 101], [5, 89], [108, 5], [115, 8]])
     8     # 四组特征的标签
     9     labels = ['爱情片', '爱情片', '动作片', '动作片']
    10     return group, labels
    11 
    12 
    13 """
    14 KNN算法,分类器
    15 参数:
    16     inX - 用于分类的数据(测试集)
    17     dataSet - 用于训练的数据(训练集)(n*1维列向量)
    18     labels - 分类标准(n*1维列向量)
    19     k - KNN算法参数,选择距离最小的k个点
    20 返回:
    21     sortedClasscount[0][0] - 分类结果
    22 """
    23 def classify0(inX, dataSet, labels, k):
    24     # numpy函数shape[0]返回dataSet的行数(维度)
    25     dataSetSize = dataSet.shape[0]
    26     # 将inX重复dataSetSize次并排成一列
    27     diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet
    28     # 二维特征相减后平方
    29     sqDiffMat = diffMat**2
    30     # sum()所有元素相加,sum(0)列相加,sum(1)行相加
    31     sqDistances = sqDiffMat.sum(axis=1)
    32     # 开方,计算出距离
    33     distances = sqDistances**0.5
    34     # argsort函数返回的是distances值从小到大的索引值
    35     sortedDistIndicies = distances.argsort()
    36     # 定义一个记录类别次数的词典
    37     classCount = {}
    38     # 选择距离最小的k个点
    39     for i in range(k):
    40         # 取出前k个元素的类别
    41         voteIlabel = labels[sortedDistIndicies[i]]
    42         # 字典的get()方法,返回指定键的值,如果值不在字典中返回0
    43         # 计算类别次数
    44         classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
    45     # reverse降序排序字典,operator.itemgetter(1)按值排序,(0)按键排序
    46     sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
    47     # 返回次数最多的类别,即所要分类的类别
    48     return sortedClassCount[0][0]
    49 
    50 # 测试
    51 group, labels = createDataSet()
    52 classify0([0,0], group, labels, 3)  # output: '爱情片'
    View Code 

    实战:手写数字识别系统

    这里只能识别数字0到9,图像为32*32像素的黑白图像,将图像转换为文本格式。

    将图像格式化处理为一个向量,把32*32的二进制图像矩阵为1*2014的向量。

     1 """
     2 将32*32的二进制图像转换为1*1024向量
     3 参数:
     4     filename - 文件名
     5 返回:
     6     returnVect - 返回二进制图像的1*1024向量
     7 """
     8 
     9 def img2vector(filename):
    10     returnVect = np.zeros((1, 1024))
    11     fr = open(filename)
    12     # 按行读取
    13     for i in range(32):
    14         # 读取一行数据
    15         lineStr = fr.readline()
    16         # 每一行的前32个数据依次存储到returnVect中
    17         for j in range(32):
    18             returnVect[0, 32*i+j] = int(lineStr[j])
    19     # 返回转换后的1*1024向量
    20     return returnVect
    21 
    22 # 测试
    23 testVector = img2vector('testDigits/0_13.txt')
    24 testVector[0, 0:31]
    25 # output: array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 1.,
    26 #        1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
    View Code

    测试算法

     1 """
     2 手写数字分类测试
     3 参数:
     4     None
     5 返回:
     6     None
     7 """
     8 def handwritingClassTest():
     9     # 测试集的labels
    10     hwLabels = []
    11     # 返回trainingDigits目录下的文件名
    12     trainingFilesList = listdir('trainingDigits')
    13     # 返回文件夹下文件的个数
    14     m = len(trainingFilesList)
    15     # 初始化训练的Mat矩阵(全零针),测试集
    16     trainingMat = np.zeros((m, 1024))
    17     # 从文件名中解析出训练集的类别
    18     for i in range(m):
    19         # 获得文件的名字
    20         fileNameStr = trainingFilesList[i]
    21         # 获得分类的数字
    22         classNumber = int(fileNameStr.split('_')[0])
    23         # 将获得的类别添加到hwLabels中
    24         hwLabels.append(classNumber)
    25         # 将每个文件的1*1024数据存储到trainingMat矩阵中
    26         trainingMat[i, :] = img2vector('trainingDigits/%s' % (fileNameStr))
    27     # 构造KNN分类器
    28     neigh = KNN(n_neighbors=3, algorithm='auto')
    29     # 拟合模型,trainingMat为测试矩阵,hwLabels为对应标签
    30     neigh.fit(trainingMat, hwLabels)
    31     # 返回testDigits目录下的文件列表
    32     testFileList = listdir('testDigits')
    33     # 错误检测计数
    34     errorCount =0.0
    35     # 测试数据的数量
    36     mTest = len(testFileList)
    37     # 从文件中解析出测试集的类别并进行分类测试
    38     for i in range(mTest):
    39         # 获得文件名字
    40         fileNameStr = testFileList[i]
    41         # 获得分类的数字
    42         classNumber = int(fileNameStr.split('_')[0])
    43         # 获得测试集的1*1024向量,用于训练
    44         vectorUnderTest = img2vector('testDigits/%s' % (fileNameStr))
    45         # 获得预测结果
    46         classifierResult = neigh.predict(vectorUnderTest)
    47         print("分类返回结果为%d	真实结果为%d" % (classifierResult, classNumber))
    48         if(classifierResult != classNumber):
    49             errorCount += 1.0
    50     print("总共错了%d个数据
    错误率为%f%%" % (errorCount, errorCount/mTest * 100))
  • 相关阅读:
    mysql--数据库的基本操作(二)
    mysql--数据库剧本指令操作
    poj_3461 KMP算法解析
    POJ_3122 经典二分题
    LIS(最长上升子序列)的 DP 与 (贪心+二分) 两种解法
    HDU_1059 多重背包问题
    HDU-1114 完全背包+恰好装满问题
    HDU _2546 01背包问题
    POJ-1611 并查集
    HDU——Monkey and Banana 动态规划
  • 原文地址:https://www.cnblogs.com/harbin-ho/p/12026276.html
Copyright © 2011-2022 走看看