机器学习实战笔记(Python)- k近邻算法(kNN)

本文详细介绍了k-近邻(kNN)算法的工作原理、适用范围和优缺点。通过电影分类的例子展示了kNN算法的决策过程,并提供了Python代码实现,包括kNN分类器的构建、数值归一化以及在手写数字识别中的应用。最后总结了kNN算法的特点和可能面临的问题。
摘要由CSDN通过智能技术生成

k-近邻算法概述

简单地说,k-近邻算法采用测量不同特征值之间的距离方法进行分类。
优点:精度高、对异常值不敏感、无数据输入假定
缺点:计算复杂度高、空间复杂度高
适用数据范围:数值型和标称型

工作原理

存在一个训练样本集,并且每个样本都存在标签(有监督学习)。输入没有标签的新样本数据后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取出与样本集中特征最相似的数据(最近邻)的分类标签。一般来说,我们只选择样本数据集中前k个最相似的数据,这就是k-近邻算法中k的出处,而且k通常不大于20。最后选择k个最相似数据中出现次数最多的分类,作为新数据的分类。

解决问题示例

以电影分类为例子,使用k-近邻算法分类爱情片和动作片。有人曾经统计过很多电影的打斗镜头和接吻镜头,下图显示了6部电影的打斗和接吻镜头数。 假如有一部未看过的电影,如何确定它是爱情片还是动作片呢?
在这里插入图片描述
第一步:首先需要统计这个未知电影存在多少个打斗镜头和接吻镜头,下图中问号位置是该未知电影出现的镜头数
在这里插入图片描述
第二步:之后计算未知电影与样本集中其他电影的距离(相似度)(相似度越小,距离越远),结果如下表所示:
在这里插入图片描述
第三步:将相似度列表排序,选出前k个最相似的样本。
第四步:统计最相似样本的分类。
第五步:将分类最多的类别作为未知电影的分类。

k-近邻算法的一般流程

在这里插入图片描述

实例:kNN分类算法的Python代码实现与解析

from numpy import *
import operator

def createDataSet():
    """
    函数作用:构建一组训练数据(训练样本),共4个样本
    同时给出了这4个样本的标签,及labels
    """
    group = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
    labels = ['A','A','B','B']
    return group,labels
    
def classify0(inX, dataSet, labels, k):
    """
    inX 是输入的测试样本,是一个[x, y]样式的
    dataset 是训练样本集
    labels 是训练样本标签
    k 是top k最相近的
    """
    
    # shape返回矩阵的[行数,列数],
    # 那么shape[0]获取数据集的行数,
    # 行数就是样本的数量
    
    dataSetSize = dataSet.shape[0]
    #print("dataSetSize=",dataSetSize)
    
    """
    下面的求距离过程就是按照欧氏距离的公式计算的。
    即 根号(x^2+y^2)
    """
    
    # tile属于numpy模块下边的函数
    # tile(A, reps)返回一个shape=reps的矩阵,矩阵的每个元素是A
    # 比如 A=[0,1,2] 那么,tile(A, 2)= [0, 1, 2, 0, 1, 2]
    # tile(A,(2,2)) = [[0, 1, 2, 0, 1, 2],
    #                  [0, 1, 2, 0, 1, 2]]
    # tile(A,(2,1,2)) = [[[0, 1, 2, 0, 1, 2]],
    #                    [[0, 1, 2, 0, 1, 2]]] 
    # 上边那个结果的分开理解就是:
    # 最外层是2个元素,即最外边的[]中包含2个元素,类似于[C,D],而此处的C=D,因为是复制出来的
    # 然后C包含1个元素,即C=[E],同理D=[E]
    # 最后E包含2个元素,即E=[F,G],此处F=G,因为是复制出来的
    # F就是A了,基础元素
    # 综合起来就是(2,1,2)= [C, C] = [[E], [E]] = [[[F, F]], [[F, F]]] = [[[A, A]], [[A, A]]]
    # 这个地方就是为了把输入的测试样本扩展为和dataset的shape一样,然后就可以直接做矩阵减法了。
    # 比如,dataset有4个样本,就是4*2的矩阵,输入测试样本肯定是一个了,就是1*2,为了计算输入样本与训练样本的距离
    # 那么,需要对这个数据进行作差。这是一次比较,因为训练样本有n个,那么就要进行n次比较;
    # 为了方便计算,把输入样本复制n次,然后直接与训练样本作矩阵差运算,就可以一次性比较了n个样本。
    # 比如inX = [0,1],dataset就用函数返回的结果,那么
    # tile(inX, (4,1))= [[ 0.0, 1.0],
    #                    [ 0.0, 1.0],
    #                    [ 0.0, 1.0],
    #                    [ 0.0, 1.0]]
    # 作差之后
    # diffMat = [[-1.0,-0.1],
    #            [-1.0, 0.0],
    #            [ 0.0, 1.0],
    #            [ 0.0, 0.9]]
    diffMat = tile(inX,(dataSetSize,1)) - dataSet   #将diffMat 变为 inX的 dataSetSize 行 ,1列
    #print("diffMat=",diffMat)
    
    # diffMat就是输入样本与每个训练样本的差值,然后对其每个x和y的差值进行平方运算。
    # diffMat是一个矩阵,矩阵**2表示对矩阵中的每个元素进行**2操作,即平方。
    # sqDiffMat = [[1.0, 0.01],
    #              [1.0, 0.0 ],
    #              [0.0, 1.0 ],
    #              [0.0, 0.81]]
    sqDiffMat = diffMat **2 #平方
    #print("sqDiffMat=
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值