《机器学习实战》笔记——第二章:k-近邻算法(kNN)实战

本文详细介绍了k-近邻(kNN)算法的实现过程,包括导入数据、算法实现、约会网站配对案例和手写识别系统案例。通过对数据的归一化处理,kNN算法在约会网站配对效果中达到了5%的错误率,并在手写数字识别中取得了0.010571的错误率。kNN算法虽然准确度高,但存在计算量大、需要保存全部数据等问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 说明

该书主要以原理简介+项目实战为主,本人学习的主要目的是为了结合李航老师的《统计学习方法》以及周志华老师的西瓜书的理论进行学习,从而走上机器学习的“不归路”。因此,该笔记主要详细进行代码解析,从而透析在进行一项机器学习任务时候的思路,同时也积累自己的coding能力。
正文由如下几部分组成:
1、实例代码(详细注释)
2、知识要点(函数说明)
3、调试及结果展示

2 正文

(1)准备:使用python导入数据

1、将如下内容写入kNN.py文件:

from numpy import *
import operator

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

知识要点:
①operator模块:该模块是python中内置的操作符函数接口,它定义了一些算术和比较内置操作的函数。接下的代码会用到该模块中的一个非常重要的方法:itemgetter

2、打开python交互式开发环境,执行以下命令并得到结果:

******
PyDev console: starting.
Python 3.6.7 |Anaconda, Inc.| (default, Oct 28 2018, 19:44:12) [MSC v.1915 64 bit (AMD64)] on win32
>>>import kNN
>>>group, labels = kNN.createDataSet()
>>>group
array([[1. , 1.1],
       [1. , 1. ],
       [0. , 0. ],
       [0. , 0.1]])
>>>labels
['A', 'A', 'B', 'B']

(2)实施kNN分类算法

1、在kNN.py文件中添加如下代码,该函数用于k-近邻算法的实现,其中4个输入分别是:输入向量inX(欲进行分类的数据),输入的训练样本集dataSet,标签向量labels以及所选k值。具体实现如下代码所示:

def classify0(inX, dataSet, labels, k):
    dataSetSize = dataSet.shape[0]#获取训练样本集的行数,即样本个数
    diffMat = tile(inX, (dataSetSize,1)) - dataSet#利用tile函数将inX向量构造成一个和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]]#把按值大小顺序排列的欧氏距离索引list前k个对应的labels遍历出来
        classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1#统计labels中各类出现的频次,以字典的形式输出
    #分解为元组列表,operator.itemgetter(1)按照第二个元素的次序对元组进行排序,reverse=True是逆序,即按照从大到小的顺序排列
    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
    return sortedClassCount[0][0]

知识要点:
①tile():tile函数位于python模块 numpy中,其功能是重复某个数组,从而形成新的数组。
②argsort():tile函数位于python模块 numpy中,其功能是将目标数组中的元素从小到大排列,提取其对应的index(索引),然后输出。
③sorted():sorted函数是python的内置函数,用来做排序任务,该函数可以对list按一定的规则进行排序。
④items():Python 字典(Dictionary) items() 函数以列表返回可遍历的(键, 值) 元组数组。返回值类型为dict_items。
⑤itemgetter():operator模块提供的itemgetter函数用于获取对象的哪些维的数据,参数为一些序号(即需要获取的数据在对象中的序号),其定义的是一个函数,通过该函数作用到对象上才能获取值。

2、我们假设现在有个待测试数据(0,0),k值选择3,下面就来预测一下该数据所在分类是什么,还是接着之前的python交互式开发环境,所得结果是B分类:

******
>>>kNN.classify0([0,0], group, labels, 3)
'B'

(3)案例1-使用k-近邻算法改进约会网站的配对效果

1、书中案例给定了3个维度的特征,共计1000组,存放在工程根目录下的datingTestSet2.txt文本文件下。在将特征数据输入到分类器之前,需要将待处理数据的格式改变为分类器可以接受的格式。案例中定义了file2matrix函数,该函数的输入为文本文件名字符串,输出为训练样本矩阵和类标签向量。具体实现代码如下:

def file2matrix(filename):
    fr = open(filename)
    numberOfLines = len(fr.readlines())#获取文件的行数
    returnMat = zeros((numberOfLines,3))#构造返回的矩阵
    classLabelVector = []#构造返回的labels列表
    fr = open(filename)#此处为何还要开一次呢?
    index = 0
    for line in fr.readlines():
        line = line.strip()#按行去除头尾字符、空白符(包括\n、\r、\t、' ',即:换行、回车、制表符、空格)
        listFromLine = line.split('\t')#拆分字符串,通过指定分隔符对字符串进行切片,并返回分割后的字符串列表(list)
        returnMat[index,:] = listFromLine[0:3]#通过切片操作抽取特征向量
        classLabelVector.append(int(listFromLine[-1]))#获取labels
        index += 1
    return returnMat,classLabelVector

知识要点:
①open():open() 函数是python内置的file对象中的一个方法,用于打开一个文件,创建一个 file 对象,相关的方法才可以调用它进行读写。
②readlines():用于读取所有行(直到结束符 EOF)并返回列表,该列表可以由 Python 的 for… in … 结构进行处理。如果碰到结束符 EOF 则返回空字符串。
③strip():用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。
④split():str.split(str="", num=string.count(str))。通过指定分隔符对字符串进行切片,如果参数 num 有指定值,则分隔 num+1 个子字符串。

2、在python交互开发环境中执行的命令和结果如下:

******
PyDev console: starting.
Python 3.6.7 |Anaconda, Inc.| (default, Oct 28 2018, 19:44:12) [MSC v.1915 64 bit (AMD64)] on win32
>>>from kNN import *
>>>datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')
>>>datingDataMat
>>>array([[4.0920000e+04, 8.3269760e+00, 9.5395200e-01],
          [1.4488000e+04, 7.1534690e+00, 1.6739040e+00],
          [2.6052000e+04, 1.4418710e+00, 8.0512400e-01],
          ...,
          [2.6575000e+04, 1.0650102e+01, 8.6662700e-01],
          [4.8111000e+04, 9.1345280e+00, 7.2804500e-01],
          [4.3757000e+04, 7.8826010e+00, 1.3324460e+00]])
>>>datingLabels[0:20]
[3, 2, 1, 1, 1, 1, 3, 3, 1, 3, 1, 1, 2, 1, 1, 1, 1, 1, 2, 3]

此处我是重新打开了交互环境,如果你是按着书上的步骤一步一步做下来的,需要reload我们创建的kNN模块。而书中例程用的是python2,reload还是属于python内置的。如果我们用的是python3,那么就要通过下面的方式进行重载:

******
PyDev console: starting.
Python 3.6.7 |Anaconda,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值