机器学习-k-近邻算法

2023-11-16

一、k-近邻算法概述

k-近邻算法是一种常用的监督学习算法,用于分类和回归任务。其思想为:如果一个样本在特征空间中的k个最近邻居中的大多数属于某个类别,那么该样本也属于这个类别(对于分类任务)或者可以通过这些最近邻居的标签来估计其目标值(对于回归任务)。

1.1 使用python导入数据

def createDataSet():
    '''
    构造数据
    
    Parameters:
        None
    Returns:
        group - 数据
        labels - 标签
    '''
    group = array([[100,98],[100,100],[0,0],[0,10]])    #[测试1的得分,测试2的得分]
    labels = ['A','A','B','B']    #整体评级情况
    return group, labels

1.2 从文本文件中解析数据

通过计算两点之间的距离来进一步选择相近的k个点:
d = ( x A 0 − x B 0 ) 2 − ( x A 1 − x B 1 ) 2 d=\sqrt{(x_{A_0}-x_{B_0})^2-(x_{A_1}-x_{B_1})^2} d=(xA0xB0)2(xA1xB1)2

def classify_KNN(inX, dataSet, labels, k):
    '''
    使用kNN算法进行分类
    
    Parameters:
        inX - 用于分类的数据(测试集)
        dataSet - 用于训练的数据(训练集)
        labels - 训练集标签
        k - kNN算法参数,选择距离最小的k个点
    Returns:
        sortedClassCount - 分类结果
    '''
    dataSetSize = dataSet.shape[0]    #dataSet的行数
    diffMat = 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]]    #获得类别信息
        classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1    #类别数量+1
    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
    return sortedClassCount[0][0]

至此,就可以通过给定数据进行分类预测,分类预测的效果与数据集的标准

二、使用k-近邻算法改进约会网站的配对效果

2.1 准备数据

海伦将自己交往过的人可以进行如下分类:不喜欢的人、魅力一般的人、极具魅力的人。
海伦收集约会数据已经有了一段时间,她把这些数据存放在文本文件datingTestSet.txt中,每个样本数据占据一行,总共有1000行。海伦收集的样本数据主要包含以下3种特征:每年获得的飞行常客里程数、玩视频游戏所消耗时间百分比、每周消费的冰淇淋公升数。

def file2matrix(filename):
    '''
    读取数据,并将其转化为矩阵
    
    Parameters:
        filename - 文件路径
    Returns:
        returnMat - 数据矩阵
        classLabelVector - 数据标签
    '''
    with open(filename, "r") as file:
        lines = file.readlines()    #读取文本信息
    
    numberOfLines = len(lines)    #计算行数
    
    returnMat = zeros((numberOfLines,3))    #初始化矩阵
    classLabelVector = []    #创建分类标签向量
    index = 0

    for line in lines:
        line = line.strip()
        listFromLine = line.split('\t')
        returnMat[index,:] = listFromLine[0:3]
        
        #根据文本中标记的喜欢的程度进行分类,1代表不喜欢,2代表魅力一般,3代表极具魅力
        if listFromLine[-1] == 'didntLike':
            classLabelVector.append(1)
        elif listFromLine[-1] == 'smallDoses':
            classLabelVector.append(2)
        elif listFromLine[-1] == 'largeDoses':
            classLabelVector.append(3)
        index += 1
    return returnMat, classLabelVector   #(1000, 3),(1000,)

2.2 数据预处理

对于不同的类别的数据分布差异可能比较大,例如游戏时长百分比的差异在0-1之间,而飞行里程往往差异成败上千不等,差异大的属性值会严重影响欧式距离。因此需要对数据进行标准化,计算公式如下:
d a t a n o r m = d a t a − d a t a m i n d a t a m a x − d a t a m i n data_{norm} = \frac{data-data_{min}}{data_{max}-data_{min}} datanorm=datamaxdatamindatadatamin

def autoNorm(dataSet):
    '''
    归一化dataset中的值,函数返回归一化后的数据
    
    Parameters:
        dataSet - 原始数据
    Returns:
        normDataSet - 归一化后的数据
        ranges - 最大最小值的差值
        minVals - 数据中的最小值
    '''
    
    minVals = dataSet.min(0)    #获得数据的最小值
    maxVals = dataSet.max(0)    #获得数据的最大值
    
    ranges = maxVals - minVals#最大值和最小值的范围
    normDataSet = zeros(shape(dataSet))    #初始化归一矩阵
    m = dataSet.shape[0]    #dataSet的行数
    normDataSet = dataSet - tile(minVals, (m, 1))    #原始值减去最小值,tile是扩充函数
    normDataSet = normDataSet / tile(ranges, (m, 1))    #除以最大和最小值的差,得到归一化数据
    
    return normDataSet, ranges, minVals

2.3 分析数据

def showdatas(datingDataMat, datingLabels):
    '''
    将数据以散点图形式展示出来。
    
    Parameters:
        datingDataMat - 数据矩阵
        datingLabels - 数据标签
    Returns:
        None
    '''
            
    color_map = {1: 'r', 2: 'g', 3: 'b'}    # 创建颜色映射,将每个标签映射到不同的颜色
    label_name = ['didntLike','smallDoses','largeDoses']

    # 根据标签分组数据点
    grouped_data = {}
    for label in np.unique(datingLabels):
        grouped_data[label] = datingDataMat[datingLabels == label]
        
    plt.figure(figsize=(18, 6))
    plt.subplot(131)    # 创建X-Y平面上的散点图
    for label, color in color_map.items():
        points = grouped_data[label]
        plt.scatter(points[:, 0], points[:, 1], c=color, label=f'{label_name[label-1]}')
    plt.xlabel('每年获得的飞行常客里程数',fontproperties=font)
    plt.ylabel('玩视频游戏所消耗时间占',fontproperties=font)
    plt.legend()

    # 创建X-Z平面上的散点图
    plt.subplot(132)
    for label, color in color_map.items():
        points = grouped_data[label]
        plt.scatter(points[:, 0], points[:, 2], c=color, label=f'{label_name[label-1]}')
    plt.xlabel('每年获得的飞行常客里程数',fontproperties=font)
    plt.ylabel('每周消费的冰激淋公升数',fontproperties=font)
    plt.legend()

    # 创建Y-Z平面上的散点图
    plt.subplot(133)
    for label, color in color_map.items():
        points = grouped_data[label]
        plt.scatter(points[:, 1], points[:, 2], c=color, label=f'{label_name[label-1]}')
    plt.xlabel('玩视频游戏所消耗时间占',fontproperties=font)
    plt.ylabel('每周消费的冰激淋公升数',fontproperties=font)
    plt.legend()

    # 显示图形
    plt.tight_layout()
    plt.show()

在这里插入图片描述

2.4 测试算法

将数据按照指定比例划分训练集与测试集,训练集用于构建模型,测试集用于评估算法与数据的可靠性。

def datingClassTest():
    """ 
    测试算法的准确度,打印出算法的错误率
    Parameters:
        None
    Returns:
        None
    """
    filename = r"./datingTestSet.txt"    #文件路径
    datingDataMat, datingLabels = file2matrix(filename)
    
    hoRatio = 0.10   #测试集比例
    normMat, ranges, minVals = autoNorm(datingDataMat)    #数据归一化
    m = normMat.shape[0]    #数据量
    numTestVecs = int(m * hoRatio)    #测试集个数
    errorCount = 0.0    #分类错误量

    for i in range(numTestVecs):    #遍历测试集,评估正确率
        classifierResult = classify_KNN(normMat[i,:], normMat[numTestVecs:m,:],datingLabels[numTestVecs:m], 4)
        #输出错误的情况
        if classifierResult != datingLabels[i]:
            errorCount += 1.0
            print("分类结果:%d\t真实类别:%d" % (classifierResult, datingLabels[i]))
    print("错误率:%f%%" %(errorCount/float(numTestVecs)*100))

2.5使用算法

调用模型就可以进行数据的预估,不同的k值也可能会有不同的结果。需要根据实际应用场景决定

def classifyPerson():
    """ 
    根据输入内容进行判断
    Parameters:
        None
    Returns:
        None
    """
    resultList = ['讨厌','有些喜欢','非常喜欢']    #输出结果
    
    precentTats = float(input("玩视频游戏所耗时间百分比:"))
    ffMiles = float(input("每年获得的飞行常客里程数:"))
    iceCream = float(input("每周消费的冰激淋公升数:"))
    
    filename = "./datingTestSet.txt"
    datingDataMat, datingLabels = file2matrix(filename)
    normMat, ranges, minVals = autoNorm(datingDataMat)

    inArr = array([precentTats, ffMiles, iceCream])
    norminArr = (inArr - minVals) / ranges
    #返回分类结果
    classifierResult = classify_KNN(norminArr, normMat, datingLabels, 3)
    #打印结果
    print("你可能%s这个人" % (resultList[classifierResult-1]))

在这里插入图片描述

三、手写体识别系统

对于手写识别系统而言整体流程是一致的,主要差距在于数据的输入以及预处理上。

def img2vector(file_path):
    """
    将32x32的二进制图像转换为1x1024向量。

    Parameters:
        file_path - 文件名
    Returns:
        returnVect - 返回的二进制图像的1x1024向量
    """
    returnVect = np.zeros((1, 1024))    #初始化
    
    with open(file_path, 'r') as file:
        for i in range(32):
            lineStr = file.readline()
            for j in range(32):
                returnVect[0, 32*i+j] = int(lineStr[j])
    
    return returnVect

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

机器学习-k-近邻算法 的相关文章

随机推荐

  • 如何安装以及用相关插件配置OBSIDIAN?

    之前看人推荐logseq就尝试了一下 吐槽跨设备同步难搞 然后被人种草了Obsidian 这几天使用下来感觉确实比logseq好用多了 第三方插件同步虽然有点冲突但大体上还好 现在考虑怎么去合理规划tag以及wiznote笔记的迁移 虽说感
  • 刷脸支付机会是留给敢迈出第一步的人

    从支付宝推出余额宝 花呗等功能大幅培养用户理财习惯 到微信支付通过微信红包打通朋友圈 微信支付和支付宝的擂台之战从未平息 面对10亿交易笔数到20亿的跨越 较量已经从扫码支付延伸至了各式各样的甚至难啃的场景 比如停车场无感支付 线下的刷脸支
  • Docker笔记(精简版)

    文章目录 初始Docker 学习背景 Docker解决依赖兼容问题 Docker解决操作系统环境差异 Docker架构 镜像和容器 DockerHub Docker架构 安装Docker 卸载 可选 安装Docker 启动docker 配置
  • VS静态编译C/C++解决程序丢失 VCRUNTIME140.dll

    VS静态编译C C 解决程序丢失 VCRUNTIME140 dll1VS静态编译C C 解决程序丢失 VCRUNTIME140 dll2VS静态编译C C 解决程序丢失 VCRUNTIME140 dll3VS静态编译C C 解决程序丢失 V
  • 【C++ 并发与多线程】std::thread类-为共享数据加锁 2

    正交 消除无关事务之间的影响 力求高内聚低耦合 死锁的概念略去不说 死锁有可能发生在使用多个互斥量的场景下 也可能存在没有使用互斥量的场景 两个线程都在等待对方释放互斥量 两个线程都调用了对方的join 函数 为了解决两个线程都在等待对方释
  • 实施前端微服务化的六七种方式

    微前端架构是一种类似于微服务的架构 它将微服务的理念应用于浏览器端 即将 Web 应用由单一的单体应用转变为多个小型前端应用聚合为一的应用 由此带来的变化是 这些前端应用可以独立运行 独立开发 独立部署 以及 它们应该可以在共享组件的同时进
  • 记一次Nginx代理Mysql服务的经历

    背景 根据组长背景描述 具备以下前提 1 Mysql服务器为 某A云厂商的RDS SAAS服务 但是不开通外网服务 2 EC2 服务器一台 某A云厂商LaaS服务 也不开通外网 3 阿里云服务器一台 这台服务器有服务需要连接Mysql服务
  • 多列索引

    单列索引与多列索引 索引可以是单列索引 也可以是多列索引 下面我们通过具体的例子来说明这两种索引的区别 假设有这样一个people表 CREATE TABLE people peopleid SMALLINT NOT NULL AUTO I
  • swiper实现无限滚动轮播、左右切换

    废话不多说 直接上代码 const mySwiper ref
  • 经典C语言程序设计100例,部分有个人注解

    经典C语言程序设计100例 程序1 题目 有1 2 3 4个数字 能组成多少个互不相同且无重复数字的三位数 都是多少 1 程序分析 可填在百位 十位 个位的数字都是1 2 3 4 组成所有的排列后再去 掉不满足条件的排列 当然这里的去掉并不
  • QT之读取文本文件中的GPS数据,并解析出经纬度

    include
  • Win10以管理员身份运行CMD命令提示符的四种方法

    方法一 1 我们可以在Windows10系统的开始菜单上 单击鼠标右键 这时候出现的菜单中 我们选择命令提示符 管理员 点击打开这样即可 方法二 1 点击开始菜单 然后界面中我们这里选择所有应用打开进入 如图所示 2 所有应用中 我们在Wi
  • QT中的库类

    目录 QFile详解 文件如果不存在则创建 判断文件是否存在 获得文件的各种详细信息 读写文件 1 QFile文件如果不存在则创建的方法 2 QFileInfo的方法获得文件的各种详细信息 3 QFile读写文件的内容 QTextStrea
  • redis集群拓扑结构自动更新:使用Lettuce连接Cluster集群实例时异常处理

    问题 使用lettuce连接Cluster集群实例 实例执行规格变更后 分片数有变化时 部分槽位 Slot 会迁移到新分片上 当客户端连接到新分片时会出现以下异常问题 java lang IllegalArgumentException C
  • Mybatis学习笔记

    文章目录 前言 1 Mybatis简介 1 1 什么是Mybatis 1 2 持久化 1 3 持久层 1 4 为什么需要Mybatis 2 第一个Mybatis程序 2 1 创建测试数据库 2 2 新建maven项目 2 2 1 新建项目
  • 计算机语句的简单练习

    1 求1000以内的水鲜花数 用while循环的方法 i 100 while i lt 1000 b int i 100 10 s int i 10 10 g int i 10 if b 3 s 3 g 3 i print i i 1 co
  • ubuntu14.04中java卸载_ubuntu如何完全卸载Java

    1 移除所有 Java相关包 Sun Oracle OpenJDK IcedTea plugins GIJ 1 apt get update 2 apt cache search java awk print 1 grep E e ia32
  • 前端响应式

    文章目录 什么是响应式 响应式web交互设计 怎么实现响应式布局 1 百分比布局 2 媒体查询 3 rem响应式布局 4 vw vh响应式布局 5 flex弹性布局 什么是响应式 总所周知 我们前端也被称为响应式web交互设计 那么什么是响
  • 搭建个人静态blog

    前言 也是无意间看到一个写个人博客的 看着非常的好看 于是乎一个牛逼而又der想法就产生了 我也要搞一个人的blog 就显摆一下 就是玩 于是这个blog就产生了 写完之后的也是非常的激动 赶紧发给朋友 显摆显摆 后来朋友也都很惊讶 确实还
  • 机器学习-k-近邻算法

    k 近邻算法 一 k 近邻算法概述 1 1 使用python导入数据 1 2 从文本文件中解析数据 二 使用k 近邻算法改进约会网站的配对效果 2 1 准备数据 2 2 数据预处理 2 3 分析数据 2 4 测试算法 2 5使用算法 三 手