K 近邻、K-NN 算法图文详解

1. 为什么学习KNN算法

KNN是监督学习分类算法,主要解决现实生活中分类问题。根据目标的不同将监督学习任务分为了分类学习及回归预测问题。

KNN(K-Nearest Neihbor,KNN)K近邻是机器学习算法中理论最简单,最好理解的算法,是一个非常适合入门的算法,拥有如下特性:

  • 思想极度简单,应用数学知识少(近乎为零),对于很多不擅长数学的小伙伴十分友好
  • 虽然算法简单,但效果也不错

2. KNN 原理

在这里插入图片描述
上图中每一个数据点代表一个肿瘤病历:

  • 横轴表示肿瘤大小,纵轴表示发现时间
  • 恶性肿瘤用蓝色表示,良性肿瘤用红色表示

疑问:新来了一个病人(下图绿色的点),如何判断新来的病人(即绿色点)是良性肿瘤还是恶性肿瘤?

在这里插入图片描述

解决方法:k-近邻算法的做法如下:
(1)取一个值k=3(k值后面介绍,现在可以理解为算法的使用者根据经验取的最优值)
(2)在所有的点中找到距离绿色点最近的三个点
(3)让最近的点所属的类别进行投票
(4)最近的三个点都是蓝色的,所以该病人对应的应该也是蓝色,即恶性肿瘤。


3. 距离度量方法

机器学习算法中,经常需要 判断两个样本之间是否相似 ,比如KNN,K-means,推荐算法中的协同过滤等等,常用的套路是 将相似的判断转换成距离的计算 ,距离近的样本相似程度高,距离远的相似程度低。所以度量距离是很多算法中的关键步骤。

KNN算法中要求数据的所有特征都用数值表示。若在数据特征中存在非数值类型,必须采用手段将其进行量化为数值。

  • 比如样本特征中包含有颜色(红、绿、蓝)一项,颜色之间没有距离可言,可通过将颜色转化为 灰度值来实现距离计算
  • 每个特征都用数值表示,样本之间就可以计算出彼此的距离来
3.1 欧式距离

在这里插入图片描述

3.2 曼哈顿距离

在这里插入图片描述

3.3 切比雪夫距离(了解)
3.4 闵式距离

闵氏距离不是一种距离,而是一组距离的定义,是对多个距离度量公式的概括性的表述。
在这里插入图片描述

其中p是一个变参数:

  • 当 p=1 时,就是曼哈顿距离;
  • 当 p=2 时,就是欧氏距离;
  • 当 p→∞ 时,就是切比雪夫距离。

根据 p 的不同,闵氏距离可以表示某一类/种的距离。


4. 归一化和标准化

样本中有多个特征,每一个特征都有自己的定义域和取值范围,他们对距离计算也是不同的,如取值较大的影响力会盖过取值较小的参数。因此,为了公平,样本参数必须做一些归一化处理,将不同的特征都缩放到相同的区间或者分布内。
在这里插入图片描述

4.1 归一化
from sklearn.preprocessing import MinMaxScaler# 1. 准备数据
data = [[90, 2, 10, 40],[60, 4, 15, 45],[75, 3, 13, 46]]
# 2. 初始化归一化对象
transformer = MinMaxScaler()
# 3. 对原始特征进行变换
data = transformer.fit_transform(data)
# 4. 打印归一化后的结果
print(data)

归一化受到最大值与最小值的影响,这种方法容易受到异常数据的影响, 鲁棒性较差,适合传统精确小数据场景

4.2 标准化
from sklearn.preprocessing import StandardScaler# 1. 准备数据
data = [[90, 2, 10, 40],[60, 4, 15, 45],[75, 3, 13, 46]]
# 2. 初始化标准化对象
transformer = StandardScaler()
# 3. 对原始特征进行变换
data = transformer.fit_transform(data)
# 4. 打印归一化后的结果
print(data)

对于标准化来说,如果出现异常点,由于具有一定数据量,少量的异常点对于平均值的影响并不大


5. K 值选择问题

KNN算法的关键是什么?

答案一定是K值的选择,下图中K=3,属于红色三角形,K=5属于蓝色的正方形。这个时候就是K选择困难的时候。

在这里插入图片描述

使用 scikit-learn 提供的 GridSearchCV 工具, 配合交叉验证法可以搜索参数组合.

from sklearn.datasets import load_iris
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV# 1. 加载数据集
x, y = load_iris(return_X_y=True)# 2. 分割数据集
x_train, x_test, y_train, y_test = \train_test_split(x, y, test_size=0.2, stratify=y, random_state=0)# 3. 创建网格搜索对象
estimator = KNeighborsClassifier()
param_grid = {'n_neighbors': [1, 3, 5, 7]}
estimator = GridSearchCV(estimator, param_grid=param_grid, cv=5, verbose=0)
estimator.fit(x_train, y_train)# 4. 打印最优参数
print('最优参数组合:', estimator.best_params_, '最好得分:', estimator.best_score_)# 4. 测试集评估模型
print('测试集准确率:', estimator.score(x_test, y_test))

6. 数据集划分

为了能够评估模型的泛化能力,可以通过实验测试对学习器的泛化能力进行评估,进而做出选择。因此需要使用一个 “测试集” 来测试学习器对新样本的判别能力,以测试集上的 “测试误差” 作为泛化误差的近似。

6.1 留出法(简单交叉验证)

留出法 (hold-out) 将数据集 D 划分为两个互斥的集合,其中一个集合作为训练集 S,另一个作为测试集 T。

from sklearn.model_selection import train_test_split
from sklearn.model_selection import StratifiedShuffleSplit
from sklearn.model_selection import ShuffleSplit
from collections import Counter
from sklearn.datasets import load_irisdef test01():# 1. 加载数据集x, y = load_iris(return_X_y=True)print('原始类别比例:', Counter(y))# 2. 留出法(随机分割)x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2)print('随机类别分割:', Counter(y_train), Counter(y_test))# 3. 留出法(分层分割)x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, stratify=y)print('分层类别分割:', Counter(y_train), Counter(y_test))def test02():# 1. 加载数据集x, y = load_iris(return_X_y=True)print('原始类别比例:', Counter(y))print('*' * 40)# 2. 多次划分(随机分割)spliter = ShuffleSplit(n_splits=5, test_size=0.2, random_state=0)for train, test in spliter.split(x, y):print('随机多次分割:', Counter(y[test]))print('*' * 40)# 3. 多次划分(分层分割)spliter = StratifiedShuffleSplit(n_splits=5, test_size=0.2, random_state=0)for train, test in spliter.split(x, y):print('分层多次分割:', Counter(y[test]))if __name__ == '__main__':test01()test02()
6.2 交叉验证法

K-Fold交叉验证,将数据随机且均匀地分成k分,每次使用k-1份数据作为训练,而使用剩下的一份数据进行测试

from sklearn.model_selection import KFold
from sklearn.model_selection import StratifiedKFold
from collections import Counter
from sklearn.datasets import load_irisdef test():# 1. 加载数据集x, y = load_iris(return_X_y=True)print('原始类别比例:', Counter(y))print('*' * 40)# 2. 随机交叉验证spliter = KFold(n_splits=5, shuffle=True, random_state=0)for train, test in spliter.split(x, y):print('随机交叉验证:', Counter(y[test]))print('*' * 40)# 3. 分层交叉验证spliter = StratifiedKFold(n_splits=5, shuffle=True, random_state=0)for train, test in spliter.split(x, y):print('分层交叉验证:', Counter(y[test]))if __name__ == '__main__':test()
6.3 留一法

留一法( Leave-One-Out,简称LOO),即每次抽取一个样本做为测试集。

from sklearn.model_selection import LeaveOneOut
from sklearn.model_selection import LeavePOut
from sklearn.datasets import load_iris
from collections import Counterdef test01():# 1. 加载数据集x, y = load_iris(return_X_y=True)print('原始类别比例:', Counter(y))print('*' * 40)# 2. 留一法spliter = LeaveOneOut()for train, test in spliter.split(x, y):print('训练集:', len(train), '测试集:', len(test), test)print('*' * 40)# 3. 留P法spliter = LeavePOut(p=3)for train, test in spliter.split(x, y):print('训练集:', len(train), '测试集:', len(test), test)if __name__ == '__main__':test01()
6.4 自助法

每次随机从D中抽出一个样本,将其拷贝放入D,然后再将该样本放回初始数据集D中,使得该样本在下次采样时仍有可能被抽到;
这个过程重复执行m次后,我们就得到了包含m个样本的数据集D′,这就是自助采样的结果。

import pandas as pdif __name__ == '__main__':# 1. 构造数据集data = [[90, 2, 10, 40],[60, 4, 15, 45],[75, 3, 13, 46],[78, 2, 64, 22]]data = pd.DataFrame(data)print('数据集:\n',data)print('*' * 30)# 2. 产生训练集train = data.sample(frac=1, replace=True)print('训练集:\n', train)print('*' * 30)# 3. 产生测试集test = data.loc[data.index.difference(train.index)]print('测试集:\n', test)

7. 可执行示例代码

以下是 K-NN 算法的实现示例代码,使用 scikit-learn 库:

import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score# 示例数据
X = np.array([[1, 2], [2, 3], [3, 4], [6, 7], [7, 8], [8, 9]])
y = np.array([0, 0, 0, 1, 1, 1])# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=42)# 创建KNN分类器
knn = KNeighborsClassifier(n_neighbors=3)# 训练模型(实际上只是存储数据)
knn.fit(X_train, y_train)# 进行预测
y_pred = knn.predict(X_test)# 计算准确率,分类算法的评估
accuracy = accuracy_score(y_test, y_pred)
print("Accuracy:", accuracy)

通过这个示例,可以看到 K-NN 算法的基本流程和实现。该算法通过计算距离来进行分类,并可以通过调整 K 值来优化模型性能。


8. K-NN 算法总结

K-NN(K-Nearest Neighbors)算法是一种基于实例的学习方法,用于分类和回归。它通过计算样本与训练集中所有样本之间的距离,选择最近的 K 个邻居,然后根据这些邻居的标签进行预测。

特点
  1. 基于实例:没有显式的训练过程,直接使用训练数据进行预测。
  2. 懒惰学习:训练阶段只是存储数据,实际的计算发生在预测阶段。
  3. 非参数化:不对数据进行任何假设。
优点
  1. 简单易实现:实现起来相对简单,理解容易。
  2. 无需假设数据分布:对数据的分布没有任何假设。
  3. 适用于分类和回归:可以同时用于分类和回归问题。
  4. 灵活性:可以处理多类别分类问题。
缺点
  1. 计算复杂度高:预测时需要计算新样本与所有训练样本的距离,计算量大,尤其是数据量大时。
  2. 存储复杂度高:需要存储所有的训练数据。
  3. 对噪音敏感:容易受到噪音和异常值的影响。
  4. 维度灾难:高维数据时,计算距离的效果会变差,需要进行降维处理。
关键
  1. 选择合适的 K 值:K 值过小容易过拟合,K 值过大容易欠拟合。通常通过交叉验证选择合适的 K 值。
  2. 距离度量:常用的距离度量方法有欧氏距离、曼哈顿距离、闵可夫斯基距离等。
  3. 特征缩放:在计算距离前,需要对特征进行标准化或归一化处理,以避免特征值范围差异导致的计算偏差。
过程
  1. 数据准备:准备训练数据集和测试数据集。
  2. 计算距离:对于每个测试样本,计算它与所有训练样本之间的距离。
  3. 选择邻居:选择距离最近的 K 个邻居。
  4. 投票或平均
    • 分类:对 K 个邻居的类别进行投票,选择出现次数最多的类别作为预测结果。
    • 回归:对 K 个邻居的目标值进行平均,作为预测结果。
  5. 输出结果:输出测试样本的预测结果。

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

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

相关文章

钉钉开放AI生态战略的真正价值到底是什么?很多人都没看懂

来源: 首席数智官 hello 大家好,我们是数字化领军者都在看的首席数智官。 关注我,每天给你讲一个商业案例。 今天我们要给你讲的是:钉钉开放AI大模型生态的战略意义到底是什么? 「谁先赢得苹果,谁就赢得…

AI大模型日报#0701:Meta发布LLM Compiler、扒一扒Sora两带头人博士论文

导读:AI大模型日报,爬虫LLM自动生成,一文览尽每日AI大模型要点资讯!目前采用“文心一言”(ERNIE-4.0-8K-latest)生成了今日要点以及每条资讯的摘要。欢迎阅读!《AI大模型日报》今日要点&#xf…

09 - matlab m_map地学绘图工具基础函数 - 绘制区域填充、伪彩色、加载图像和绘制浮雕效果的有关函数

09 - matlab m_map地学绘图工具基础函数 - 绘制区域填充、伪彩色、加载图像和绘制浮雕效果的有关函数 0. 引言1. 关于m_pcolor2. 关于m_image3. 关于m_shadedrelief4. 关于m_hatch5. 结语 0. 引言 本篇介绍下m_map中区域填充函数(m_hatch)、绘制伪彩色图…

数据库连接池满问题

概述 当数据库连接池满时,可能会导致新的数据库连接请求无法被处理,进而影响应用程序与数据库的交互。以下是针对数据库连接池满问题的详细分析和解决策略: 问题分析 连接泄漏:应用程序在使用完数据库连接后没有正确地关闭连接&…

2.2章节python的变量和常量

在Python中,变量和常量有一些基本的概念和用法,但需要注意的是,Python本身并没有内置的“常量”类型。然而,程序员通常会遵循一种约定,即使用全部大写的变量名来表示常量。 一、变量 在Python中,变量是一…

唯一ID:雪花算法介绍与 Go 语言实现

介绍 snowflake 雪花算法可以在不依赖数据库的情况下,生成全局唯一的ID。雪花算法生成的ID是一个64位的整数,它由以下4部分组成: 时间戳:占用41位,精确到毫秒级,用于记录时间戳,差值形式可以使用69年。数…

数据库设计规范详解

一、为什么需要数据库设计 1、我们在设计数据表的时候,要考虑很多问题。比如: (1) 用户都需要什么数据?需要在数据表中保存哪些数据? (2) 如何保证数据表中数据的 正确性,当插入、删除、更新的时候该进行怎样的 约束检査 ?. (3) 如何降低数据表的 数据…

每天一个数据分析题(三百八十五)- 回归模型

在回归模型中,下列哪一项在权衡欠拟合(under-fitting)和过拟合(over-fitting)中影响最大? A. 多项式阶数 B. 更新回归参数w时,使用的是协方差矩阵求逆还是梯度下降 C. 使用常数项 D. 以上都…

python导入未找到tensorrt,No module named ‘tensorrt‘

(2024.7.1) 这个错误可能比较少见,是因为本人先装了tensorrt 10.1(能够正常运行),后面又装了nvidia-tensorrt 7,后面不想用7了就把7卸了用回10,结果即使同一版本的tensorrt和nvidia-tensorrt都装了&#x…

毫米波雷达深度学习技术-2.1~2.2深度度量学习和成对方法

2 深度度量学习 有几种雷达应用程序旨在对一组预定义的类别进行分类,例如不同的人类活动或手势。然而,在实际环境中,存在的类不仅仅是预定义的类,这就把问题变成了一个开放集的分类任务。开放集分类意味着网络应该能够检测输入是否…

[AIGC] StarRocks 快速了解

星石数据库(StarRocks)是一种高性能、分布式的列式存储数据库系统,旨在为大规模数据分析提供快速和可靠的解决方案。它由StarRocks团队于2015年开始开发,最初是由中国电子科技集团公司(CETC)内部项目&#…

Chapter 8 Feedback

Chapter 8 Feedback 这一章我们介绍feedback 反馈运放的原理. 负反馈是模拟电路强有力的工具. 8.1 General Considerations 反馈系统如下图所示 Aolamp open-loop gain即开环增益. Aolxo/xi β \beta β 是 feedback factor, 注意方向. β x f x o \beta\frac{x_{f}}{x_{o…

Python内置函数enumerate 将可迭代对象组合成索引序列列举出数据和数据下表

enumerate 是一个内置的 Python 函数,用于将一个可迭代对象(如列表、元组、字符串等)组合为一个索引序列,同时列出数据和数据下标。 参数说明: enumerate(iterable, start0) 接受两个参数: iterable&…

从零开始:Java开发者的设计模式指南

从零开始:Java开发者的设计模式指南 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天我们将深入探讨Java开发中的设计模式,这是每位J…

一、课程介绍,基础—环境安装、判断、循环语句等(爬虫及数据可视化)

一、课程介绍,基础—环境安装、判断、循环语句等(爬虫及数据可视化) 1. 课程介绍1.1 相关内容1.2 学习目标1.3 学习内容安排 2. python2.1 环境配置2.2 标识符和关键字2.3 运算符2.4 判断语句2.5 循环语句 1. 课程介绍 1.1 相关内容 10天的…

【pytorch11】高阶操作

高阶操作 WhereGather where 三个参数,第一个是condition,第二个参数是源头A,第三个参数是源头B,也就是说有两项数据A和B,C有可能来自于A也有可能来自于B,如果全部来自于A的话直接赋值给A,如果…

算法金 | Transformer,一个神奇的算法模型!!

大侠幸会,在下全网同名「算法金」 0 基础转 AI 上岸,多个算法赛 Top 「日更万日,让更多人享受智能乐趣」 抱个拳,送个礼 在现代自然语言处理(NLP)领域,Transformer 模型的出现带来了革命性的变…

推送本地代码库到gitee

方式一: 1、在gitee创建代码库 2、下拉到本地 git clone https:xxxx 3、将要上传的代码复制进去 4、git add . 5、git commit -m 6、git push -u origin master 成功 方式二: 1、在gitee创建代码库 2、将要上传的代码库执行 git init 3、gi…

无线物联网练习题

文章目录 选择填空简答大题 选择 不属于物联网感知技术的是(A) A:ZigBee B:红外传感器 C:FRID D:传感器 ZigBee是一种无线通信技术,虽然它常用于物联网中作为设备之间的通信手段,但它本身并不是一种感知技术 关于物联网于与互联网的区别的描述&#xff…

【机器学习】基于Transformer的迁移学习:理论与实践

引言 在机器学习领域,迁移学习已成为提升模型训练效率和性能的重要策略,特别是在标注数据稀缺的场景下。Transformer模型自2017年由Google提出以来,在自然语言处理(NLP)领域取得了突破性进展,并逐渐扩展到…