机器学习(一)-K近邻算法(KNN)原理剖析及python源码

news2025/1/16 18:55:22

介绍第一个机器学习算法:k-近邻算法,它非常有效而且易于掌握。首先,我们将探讨k-近邻算法KNN的基本理论,以及如何使用距离测量的方法分类物品;其次我们将使用Python从文本文件中导入并解析数据;再次,本书讨论了当存在许多数据来源时,如何避免计算距离时可能碰到的一些常见错误;最后,利用实际的例子讲解如何使用k-近邻算法改进约会网站。

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

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

缺点:计算复杂度高、空间复杂度高;

必须要有接近实际数据的训练样本数据,所以必须保存全部数据集,若训练数据集很大则需要使用大量的存储空间。由于又必须对数据集中的每个数据计算距离值,实际使用时可能会非常耗时(优化实现:kd树)。

适用数据范围:数值型和标称型

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

k值的选择:交叉验证法

Kd树构造算法:给定一个目标点,搜索其最近邻。首先找到包含目标点的叶结点;然后从该叶结点出发,依次回退到父结点:不断查找与目标点最邻近的结点,当确定不可能存在更近的结点时终止。这样搜索就被限制在空间的局部区域上,效率大为提高。

案例(电影分类):首先计算未知电影与样本集中其他电影的距离,如表2-2所示。此处暂时不要关心如何计算得到这些距离值,使用Python实现电影分类应用时,会提供具体的计算方法。

在我们得到了样本集中所有电影与未知电影的距离,按照距离递增排序,可以找到k个距离最近的电影。假定k=3,则三个最靠近的电影依次是He’s Not Really into DudesBeautiful WomanCalifornia Mank-近邻算法按照距离最近的三部电影的类型,决定未知电影的类型,而这三部电影全是爱情片,因此我们判定未知电影是爱情片。

伪代码:

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

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

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

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

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

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

Python3实现完整代码:

import pandas as pd
from numpy import *
import operator
import numpy as np


def knn_classify(inX, data_set, labels, k):  # KNN算法实现
    data_set_size = data_set.shape[0]
    # 计算欧式距离
    diffMat = tile(inX, (data_set_size, 1)) - data_set  # 距离矩阵
    sqDiffMat = diffMat ** 2
    sqDistances = sqDiffMat.sum(axis=1)
    distances = sqDistances ** 0.5

    # 距离从小到大排序
    sortedDistIndicies = distances.argsort()
    # 获取前k个距离最小元素所在分类,计算各分类发生频率
    class_count = {}
    for i in range(k):
        voteIlabel = labels[sortedDistIndicies[i]]
        class_count[voteIlabel] = class_count.get(voteIlabel, 0) + 1
    # 发生频率从大到小排序
    sorted_class_count = sorted(class_count.items(), key=operator.itemgetter(1), reverse=True)
    return sorted_class_count[0][0]  # 返回频率最高的标签作为最终分类


if __name__ == '__main__':
    # 1、准备数据
    group = np.array([[1.0, 1.1], [1.0, 1.0], [0, 0], [0, 0.1]])
    labels = ['A', 'A', 'B', 'B']
    import matplotlib.pyplot as plt

    plt.scatter([g[0] for g in group], [g[1] for g in group], marker='.', color='black', s=20)
    for i in range(group.shape[0]):
        plt.text(group[i][0], group[i][1], labels[i])  # 加标签
    plt.show()
    # 2、KNN算法实现
    k = 3
    knn_classify([0, 0], group, labels, k)
    # 3、算法测试(以相亲约会数据为例)
    data = pd.read_table("E:\datingTestSet.txt", header=None, sep="\t")
    data.columns = ["里程数/年", "游戏时间占比", "冰淇淋公升数/周", "匹配类型"]
    datingDataMat = data[["里程数/年", "游戏时间占比", "冰淇淋公升数/周"]].to_numpy()
    datingLabels = data[["匹配类型"]].to_numpy()
    datingLabels = [d[0] for d in datingLabels]  # 去列表并数值化
    datingLabels = [1 if d == 'didntLike' else d for d in datingLabels]
    datingLabels = [2 if d == 'smallDoses' else d for d in datingLabels]
    datingLabels = [3 if d == 'largeDoses' else d for d in datingLabels]
    # 3-1、画图统计描述
    import matplotlib.pyplot as plt
    # 游戏时间占比和冰淇淋公升数
    plt.scatter(datingDataMat[:, 1], datingDataMat[:, 2], 15 * np.array(datingLabels), 15 * np.array(datingLabels))
    plt.show()
    # 里程数和游戏时间占比
    plt.scatter(datingDataMat[:, 0], datingDataMat[:, 1], 15 * np.array(datingLabels), 15 * np.array(datingLabels))
    plt.show()
    # 3-2、数值归一化
    minVals = datingDataMat.min(0)
    maxVals = datingDataMat.max(0)
    ranges = maxVals - minVals
    m = datingDataMat.shape[0]  # 行数
    norm_data_set = datingDataMat - np.tile(minVals, (m, 1))  # tile是将minVals的行重复m次,列重复1次
    norm_data_set = norm_data_set / np.tile(ranges, (m, 1))
    # 3-3、测试验证
    hoRatio = 0.10  # hold out 10%
    m = norm_data_set.shape[0]
    numTestVecs = int(m * hoRatio)  # 验证集数量
    errorCount = 0.0
    for i in range(numTestVecs):
        classifierResult = knn_classify(norm_data_set[i, :], norm_data_set[numTestVecs:m, :], datingLabels[numTestVecs:m], 3)
        print("the classifier came back with: %d, the real answer is: %d" % (classifierResult, datingLabels[i]))
        if classifierResult != datingLabels[i]:
            errorCount += 1.0
    print("error count: ", errorCount)
    print("the total error rate is: %f" % (errorCount / float(numTestVecs)))
    # 4、算法使用
    result_list = ['not at all', 'in small doses', 'in large doses']
    ff_miles = float(input("frequent flier miles earned per year?"))
    percent_tats = float(input("percentage of time spent playing video games?"))
    ice_cream = float(input("liters of ice cream consumed per year?"))
    in_array = np.array([ff_miles, percent_tats, ice_cream])
    classifier_result = knn_classify((in_array-minVals) / ranges, norm_data_set, datingLabels, 3)
    print("You will probably like this person: ", result_list[classifier_result-1])

备注:

datingTestSet数据集直接去源码地址下载www.manning.com/MachineLearninginAction

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/443600.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaSE学习进阶day06_02 Set集合和Set接口

第二章 Set系列集合和Set接口 Set集合概述:前面学习了Collection集合下的List集合,现在继续学习它的另一个分支,Set集合。 set系列集合的特点: Set接口: java.util.Set接口和java.util.List接口一样,同样…

D. Marcin and Training Camp(思维 + 判断一个数二进制位是否是另一个数的子集)

Problem - D - Codeforces 马辛是他大学里的一名教练。有N个学生想参加训练营。马辛是个聪明的教练,所以他只想派那些能冷静合作的学生参加。 让我们关注一下这些学生。每个学生可以用两个整数ai和bi来描述;bi等于第i个学生的技能水平(越高越…

【刷题之路】LeetCode 程序员面试金典 08.03. 魔术索引

【刷题之路】LeetCode 程序员面试金典 08.03. 魔术索引 一、题目描述二、解题1、方法1——暴力法1.1、思路分析1.2、代码实现 2、方法2——二分分治2.1、思路分析2.2、代码实现 一、题目描述 原题连接: 面试题 08.03. Magic Index LCCI 题目描述: 魔术索…

计算机网络考试复习——第三章 3.3

3.3 使用广播信道的数据链路层 3.3.1局域网的数据链路层 局域网最主要的特点: 1.网络为一个单位所拥有; 2.地理范围和站点数目均有限。 局域网具有如下主要优点: 1.具有广播功能,从一个站点可很方便地访问全网。 2.便于系统…

分布式问题,你知道几个?

你好,我是田哥 现在的单体服务是很难应付面试了,必须要把分布式相关技术给讲清楚,否则面试难搞。 下面我们来聊聊,分布式环境下会面临哪些问题。 先来看一下主要内容: 分布式系统中常见的难题包括: 一致性问…

PackageMS 启动

1.PackageMS 相关框架类 2.PackageMS 启动过程 2.1 # SystemServer.java /** 291 * The main entry point from zygote. 292 */ 293 public static void main(String[] args) { 294 new SystemServer().run(); 295 } 上面是SystemServer的主函数。 pr…

RK3568开发板 buildroot编译配置

启扬智能RK3568开发板提供两种文件系统,一种是Debian,另外一种是BuildRoot。在使用过程中,有些客户需要添加属于自己的软件包,所以在此分享启扬RK3568关于BuildRoot编译配置的方法以及相关注意事项。 启扬提供的源码是完整sdk&am…

毕业论文用什么流程图软件比较好?

在写作论文的时候使用流程图,会让我们的论文看起来更加有逻辑。并且流程图的图片都可以在PPT中随意插入以及使用。 基础流程图作为最为基本和简单的的流程图方式,一般不区分用户角色和场景,适用于简单场景,梳理单一的流程情况&am…

nssctf web入门(8)

目录 [SWPUCTF 2021 新生赛]easy_sql [SWPUCTF 2021 新生赛]error 这里通过nssctf的题单web安全入门来写,会按照题单详细解释每题。题单在NSSCTF中。 想入门ctfweb的可以看这个系列,之后会一直出这个题单的解析,题目一共有28题,…

mysql(8.0)_主从复制

1.环境介绍 自己的主机--master 同学的主机--slave2.安装mysql https://blog.csdn.net/weixin_45955039/article/details/130144515?spm1001.2014.3001.55013. 准备工作 3.1在云服务器上添加端口号 3.2关闭防火墙 systemctl stop firewalld setenforce 04.master上的配置 …

数字图像处理笔记 第二章 数字图像基础

第二章 数字图像基础 2.1 视觉感知要素 知己知彼,百战不殆。了解人类的视觉感知,有助于我们学习数字图像处理。本小节中眼睛中图像的形成,让我联想到照相机成像,人眼的亮度适应和辨别让我想到手机屏幕的自动调节亮度。由于这部分…

马尔科夫链HMM

在机器学习算法中,马尔可夫链(Markov chain)是个很重要的概念。马尔可夫链(Markov chain),又称离散时间马尔可夫链(discrete-time Markov chain),因俄国数学家安德烈马尔可夫(俄语&a…

如何排查线上环境CPU100%问题

如何排查线上环境CPU100%问题 cpu爆满的原因可能:1、形成了死锁。2、形成了死循环 1.使用arthas 2.使用命令的方式 死锁的检查: 方式一: 可通过jps或者ps -ef | grep java的命令查看到运行程序的PID使用jstack -l pid 命令查看线程的堆栈信…

代码随想录|day49|动态规划part10● 121. 买卖股票的最佳时机 ● 122.买卖股票的最佳时机II

它来了它来了!我们最爱的股票问题它来了!! 121. 买卖股票的最佳时机 链接:代码随想录 视频链接:动态规划之 LeetCode:121.买卖股票的最佳时机1_哔哩哔哩_bilibili 好难懂,尤其是理解状态的变化以…

openGauss 5.0企业版主从部署,实战狂飙

📢📢📢📣📣📣 哈喽!大家好,我是【IT邦德】,江湖人称jeames007,10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】!😜&am…

【排序】归并排序(递归和非递归)

归并排序 前言图解大致思路代码实现递归非递归 时间复杂度和空间复杂度 前言 这是我讲的最后一个排序了,归并排序难度不大,也是分治的思想。 归并排序时间复杂度是在N*logN里面还是比较优的,毕竟实现起来的是完全二分的,但是差就…

2023第十届大唐杯省赛心得体会总结

第十届“大唐杯”全国大学生新一代信息通信技术大赛结束,分享一下2023第十届大唐杯省赛的相关经验。 年初研究生组就开始报名了,所以这回也是摩拳擦掌,加上大唐杯的认可度很高,今年的情况只会更卷,需要掌握一定的通信…

java数据结构学习第三期

给你一个链表的头节点 head ,判断链表中是否有环。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(…

4.17-4.18学习总结

MD5 MD5: 1、压缩性 2、容易计算 3、抗修改性 4、弱抗碰撞 5、强抗碰撞 为什么需要MD5? 存储一些敏感信息的时候,如果不进行加密会出现安全问题。 例如:系统登录的密码,如果数据库中的密码采用明文,一旦数据库泄…

扬帆优配|多路资金扎堆博弈,顶级游资章盟主3天爆买21个亿

4月20日,中科曙光(603019.SH)盘中稳步拉升,最终收涨9.99%,股价一举刷出了历史新高,达到了54.71元/股,全天的成交额也高达97.43亿元。 盘后发表的龙虎榜数据显现,知名游资章盟主的常用…