欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

《机器学习实战》第二章 k-近邻算法 详细注释

程序员文章站 2022-03-08 17:26:10
...

考研结束,算起来有半年没写程序啦,基础函数都有些记不清了,所以代码基本上每一行都写上了注释,帮助理解记忆。

疫情严重,不能出门,那就宅在家里一起学习吧~ 争取日更!

章节内容

  • k-近邻算法的基本理论;
  • 如何使用距离测量的方法分类物品;
  • 使用Python从文本文件中导入并解析数据;
  • 当存在许多数据来源时,如何避免计算距离时可能碰到的一些常见错误;
  • 使用k-近邻算法改进约会网站和手写数字识别系统。

k-近邻算法概述工作原理

训练样本集中每个数据都存在标签,即我们知道样本集中每一数据与所属分类的对应关系。输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本集中特征最相似数据(最近邻)的分类标签。一般来说,只选择样本数据集中前k个最相似的数据,通常k是不大于20的整数。最后,选择k个最相似数据中出现次数最多的分类,作为新数据的分类。

例如电影分类,使用kNN确定它是爱情片还是动作片。

表2-1 每部电影的打斗镜头数、接吻镜头数以及电影评估类型《机器学习实战》第二章 k-近邻算法 详细注释

开发机器学习应用的通用步骤
1. 收集数据
2. 准备输入数据, 确保数据格式符合要求,本书采用的格式是Python语言的List。
3. 分析输入数据,确保数据中没有垃圾数据。
4. 训练算法(kNN不需要此步)
5. 测试算法,评估算法,计算错误率。
6. 使用算法

使用k-近邻算法将每组数据划分到某个类中,伪代码如下:

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

构建分类器——

def classify0(inX, dataSet, labels, k):
    #用于分类的输入向量是inX,输入的训练样本集为dataSet,标签向量为labels,最后的参数k表示用于选择最近邻居的数目
    dataSetSize = dataSet.shape[0]  # shape[0]是读取矩阵第一维度的长度,即数据的条数
    # 计算距离
    diffMat = tile(inX, (dataSetSize,1)) - dataSet  #将目标复制成n行,计算得目标与每个训练数值之间的数值之差。
    sqDiffMat = diffMat**2  #各个元素分别平方
    sqDistances = sqDiffMat.sum(axis=1)  #对应行的平方相加,即得到了距离的平方和
    distances = sqDistances**0.5  #开根号,得到距离
    #排序,确定前k个距离最小元素所在的主要分类
    sortedDistIndicies = distances.argsort()  #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]

错误率是常用的评估方法。错误率 = 分类器给出错误结果的次数除以测试执行的总数。

以下测试代码可直接运行——

'''
构造kNN分类器
'''

from numpy import *
import operator  #运算符模块
# 创建数据集和标签

group = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
labels = ['A','A','B','B']

def classify0(inX, dataSet, labels, k):
    #用于分类的输入向量是inX,输入的训练样本集为dataSet,标签向量为labels,最后的参数k表示用于选择最近邻居的数目
    dataSetSize = dataSet.shape[0]  # shape[0]是读取矩阵第一维度的长度,即数据的条数
    # 计算距离
    diffMat = tile(inX, (dataSetSize,1)) - dataSet  #将目标复制成n行,计算得目标与每个训练数值之间的数值之差。
    sqDiffMat = diffMat**2  #各个元素分别平方
    sqDistances = sqDiffMat.sum(axis=1)  #对应行的平方相加,即得到了距离的平方和
    distances = sqDistances**0.5  #开根号,得到距离
    #排序,确定前k个距离最小元素所在的主要分类
    sortedDistIndicies = distances.argsort()  #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]

print("该数据的类别是" + classify0([0, 0],group, labels, 3))

以下是本代码中的一些(可能小白都知道的)细节——

.pyc文件
py文件作为模块被import时,python编译后产生pyc文件,目的是提高解析速度。当有别的程序再次import此模块时,python读入pyc文件即可,无需重新解析py文件。

shape函数
是numpy中的函数,功能是读取矩阵的长度。
shape[0] 读取矩阵第一维度的长度

tile函数
是numpy中的函数,将原矩阵横向、纵向地复制。tile 是瓷砖的意思,顾名思义,这个函数就是把数组像瓷砖一样铺展开来。
tile(mat, (3, 4)) 将矩阵mat复制成3*4块

** 代表乘方,开根号就是 **0.5

axis=1
第0轴沿着行的垂直往下,第1轴沿着列的方向水平延伸。
《机器学习实战》第二章 k-近邻算法 详细注释
a = np.sum([[1, 1, 1], [2, 2, 2]], axis=0)
输出[3 3 3],每列之和

a = np.sum([[1, 1, 1], [2, 2, 2]], axis=1)
输出[3 6],每行之和

argsort()
argsort函数返回的是数组值从小到大的索引值。

range()
range()是python的内置函数, 语法:range(start, stop[, step])
range(5)即前5个数, range(0,5)实际上就是索引从0开始到4结束的5个整数。step是步长,默认步长为1。

itemgetter函数
根据某个或某几个字典字段来排序Python列表。

报错 ‘dict’ object has no attribute 'iteritems’
在python3报错,将iteritems改为items即可。iteritems是为python2环境中dict的函数。

相关标签: 机器学习