机器学习笔记(四)——聚类算法KNN、Kmeans、Dbscan

写在前面:

写本系列(自用)的目的是回顾已经学过的知识、记录新学习的知识或是记录心得理解,方便自己以后快速复习,减少遗忘。概念部分大部分来自于机器学习菜鸟教程,公式部分也会参考机器学习书籍、阿里云天池。机器学习如果只啃概念始终学不牢,因此我打算概念与代码结合。

Part 2 机器学习算法

五、KNN

1、KNN的基本原理

KNN,也叫K近邻算法,是一种简单且常用的分类和回归算法。它是监督学习的一种,核心思想是通过计算待分类样本与训练集中各个样本的距离,找到距离最近的 K 个样本,然后根据这 K 个样本的类别或值来预测待分类样本的类别或值。

现在举一个例子,示例中的图片来自b站up小萌Annie的K近邻算法视频:

假设有两种狼群,狼群A和狼群B。其中,狼群A的脚印用图中绿色的圆圈来表示,狼群B的脚印用图中绿色的正方形来表示。现在给出一个不知道类别的脚印(图中黑色爪印),问这个脚印是狼群A留下的还是狼群B留下的。解决这个问题可以使用KNN算法。

假设我们设置KNN的距离超参数k = 1。也就是说,以待分类样本(黑色爪印)为圆心,k=1为半径画圆,看圆内哪种脚印数量多。例如图中,当k = 1时,圆圈的数量为1,方形的数量为0,因此我们判断黑色脚印是圆形,即待分类样本属于狼群A。

同理,k = 3时,圆圈的数量为2,方形的数量为1,因此我们判断黑色脚印是圆形,即待分类样本属于狼群A。

k = 5时,圆圈的数量为2,方形的数量为3,因此我们判断黑色脚印是方形,即待分类样本属于狼群B。

这就是KNN算法解决分类问题的案例(解决回归问题就是取k个最近邻点的平均值)。那么需要解决的问题就是KNN算法的距离如何度量。

2、距离度量(可以只了解欧氏距离)

这里shun'dai常用的距离度量方法如下:

(1)欧式距离

欧式距离是KNN最常用的距离度量,计算n维空间中两点x、y的直线距离的公式为:

d(x, y)=\sqrt{\sum_{i=1}^{n} (x_i-y_i)^2}

(2)曼哈顿距离

计算n维空间中两点在网格状空间中的最短路径距离,如城市街区距离:

d(x, y)=\sum_{i=1}^{n} |x_i-y_i|

(3)切比雪夫距离 

表示两点在各维度上差值的最大值:

d(x, y)=max_i|x_i-y_i|

(4)闵可夫斯基距离

是欧氏距离和曼哈顿距离的广义形式:

d(x, y)=(\sum_{i=1}^{n} |x_i-y_i|^p)^{\frac{1}{p}}

当p=1时为曼哈顿距离,p=2时是欧式距离,p趋于无穷时等价于切比雪夫距离。 

(5)余弦相似度 

衡量两个n维向量方向的相似性:

d(x, y)=1-\frac{x*y}{||x||*||y||}=1-\frac{\sum_{i=1}^{n}x_iy_i}{sqrt{\sum_{i=1}^{n}x_i^2}*sqrt{\sum_{i=1}^{n}y_i^2}}

这里,分子是两个向量x、y的点积;分母是向量模长的乘积。

(6)汉明距离

两个等长字符串对应位置不同字符的数量,常用于分类变量:

d(x, y) = 不同位置的数量

(7)马氏距离

考虑数据分布协方差的距离度量,消除特征间的相关性:

d(x, y)=\sqrt{(x-y)^T S^{-1}(x-y)}

其中,S是数据的协方差矩阵。

(8)编辑距离

将一个字符串转换为另一个字符串所需的最少编辑操作次数(插入、删除、替换)。

在KNN中,距离度量的选择直接影响算法性能。不同距离函数会导致不同的近邻定义,从而影响结果,最常用的距离是欧氏距离。

例如,图像识别,地理坐标分析等常用欧氏距离;文本分类等常用余弦相似度;棋盘游戏可以考虑切比雪夫距离。如果难以抉择如何选取距离,可以通过交叉验证比较不同距离函数的性能。

3、KNN步骤总结

KNN算法的步骤可以概括如下:

1、计算距离:计算待分类样本与训练集中每个样本的距离。

2、选择k个最近邻样本。

3、投票或取平均:对于分类问题,K 个最近邻中出现次数最多的类别即为待分类样本的类别;对于回归问题,K 个最近邻的值的平均值即为待分类样本的值。

4、KNN的代码实现

from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score# 加载Iris数据集
iris = datasets.load_iris()
X = iris.data # 只取前两个特征
y = iris.target# 将数据集拆分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)# 创建KNN模型,设置K值为3
knn = KNeighborsClassifier(n_neighbors=3)
'''
这里是默认使用欧氏距离,也就是:
knn = KNeighborsClassifier(n_neighbors=3, metric='euclidean')
metric就是选择距离度量方式,'euclidean'是欧式距离
'manhattan'是曼哈顿、'chebyshev'是切比雪夫、'cosine'是余弦、'hamming'是汉明、'mahalanobis'是马氏距离
metric='minkowski', p=2这样是参数为2的闵可夫斯基距离
当然,也可以自定义距离函数
写好函数后将函数传入,即 metric= 函数名 即可。
'''# 训练模型
knn.fit(X_train, y_train)# 在测试集上进行预测
y_pred = knn.predict(X_test)# 计算准确率
accuracy = accuracy_score(y_test, y_pred)
print(f"KNN模型的准确率: {accuracy:.4f}")

六、k-means

1、k-means的原理 

k-means算法也是一种经典的无监督学习算法。它的目标是:将n个数据点划分为k个簇,每个簇由其质心代表,使得所有数据点到其所属质心的平方和距离最小。

2、算法步骤 

1、初始化:随机选取k个数据点作为初始的质心;

2、分配:将每个数据点分配到距离最近的质心所在的簇;(这里默认使用且最常使用的是欧式距离,也可以使用其他距离度量方式)

3、更新:重新计算每个簇的质心,质心的计算是对簇内所有数据点的每个维度取平均值。

例如某簇里有三个点:(1, 2),(3, 4),(5, 6),该簇的中心就是(3, 4)。=>((1+3+5)/3,(2+4+6)/3)

4、迭代:重复步骤 2-3,直到质心不再变化或达到最大迭代次数。

3、示例

示例来源于b站up平安喜悦孙瑜的k-means聚类算法讲解视频。

1、初始化三个质心:黄、蓝、绿

 2、对每个白色的点,分别计算它到这三个质心的距离。离哪个质心近,就把它归为那一类。每个点均分类完成后如下图:

 3、计算出三个类的质心,作为新的簇中心:

4、算出簇中心后,重新计算每个点离三个质心的距离,重新分类;一直循环直到质心不再变化或者达到最大迭代次数。

4、代码实现

from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt# 生成模拟数据(3个簇)
X, _ = make_blobs(n_samples=300, centers=3, cluster_std=0.60, random_state=42)# 构建 K-means 模型
kmeans = KMeans(n_clusters=3, init='k-means++', max_iter=300, random_state=42)
y_pred = kmeans.fit_predict(X)# 可视化结果
plt.scatter(X[:, 0], X[:, 1], c=y_pred, cmap='viridis')
plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1], s=300, c='red', marker='X')
plt.title('K-means Clustering')
plt.show()

七、DBSCAN

1、算法原理

DBSCAN是一种基于密度的空间聚类算法,能够将高密度区域划分为簇,并将低密度区域识别为噪声点。DBSCAN中有以下几个核心概念:

设有n个待聚类点,当前操作点设为p点。

1、ε 邻域:以点 p 为中心、半径为 ε 的区域。如下图所示,p点为中心, ε =2,黑色圆内即为ε 邻域。

2、MinPts:核心点最小点数,由用户指定。

3、核心点:若点 p 的 ε 邻域内至少包含 MinPts 个点,则 p 是核心点。如下图所示:设MinPts为4,此时p点的ε 邻域内恰好有4个点(包含p本身),则p为核心点:

4、边界点:若点 p 的 ε 邻域内点的数量少于 MinPts,但它属于某个核心点的 ε 邻域,则 p 是边界点。如图,设Minpts =  4,已知核心点Q。如图,p点领域内只有两个点,因此p不是核心点,但是p在Q的ε 邻域内,因此p是边界点:

5、噪声点:既不是核心点也不是边界点的点。如下图所示,依然设MinPts = 4,p中只有两个点,小于MinPts,所以p不是核心点。又因为p也不属于其他核心点的ε 邻域领域,p也不是边界点。因此,p是噪声点:

6、直接密度可达:若点 q 在核心点 p 的 ε 邻域内,则称 q 从 p 直接密度可达。

7、间接密度可达:若q1不在核心点p的ε 邻域内,q2在核心点p的ε 邻域内,且q1在q2的ε 邻域内,那么q1与p间接密度可达。

2、算法流程

1、参数设置:指定ε和 MinPts。

2、遍历所有的点:

    若点 p 是核心点,创建一个新簇,并递归地将所有从 p 密度可达(直接+间接)的点加入该簇。

    若点 p 是边界点或噪声点,暂时标记为未分类。

3、完成分类

3、算法示例

对以下数据点使用DBSCAN算法进行聚类。

这里指定ε = 2, MinPts = 3。

如图,对点A以2为半径画圆,可得A、B、C、D都在圆内,则A为核心点,可得第一个类:{A,B,C,D}。

同理对B、C画圆,B、C都是核心点,由于B、C都在第一个类中了,因此没有新建类别,并且B、C的邻域中没有包含新的点,类别1仍为:{A,B,C,D}。接下来对D以2为半径画圆:

可见,D也是核心点,且D中包含了J,因此类别1进行更新:{A,B,C,D,J}。现在以E为圆心,2为半径画圆:

可以看出,E也是核心点,E、F、G都在圆内。由于此时并没有类别包含E,因此新建一个类2:{E、F、G}。至此,我们已经有两个类别:{A,B,C,D,J}、{E、F、G}。

同理,对F、G画圆,F、G都是核心点,由于F、G都在第二个类中了,因此没有新建类别,并且F、G的邻域中没有包含新的点,类别2仍为:E、F、G}。接下来,以点H为半径,2为圆心画圆:

此时,H的邻域里只有两个点,H不是核心点,并且H此时也不能确定是不是边界点,因此暂时将H标记为噪声点。

接下来,以点I为半径,2为圆心画圆。I的邻域中有三个点:H、I、J。因此I是核心点。由于J已经属于类别1:{A,B,C,D,J},因此I、H均加入类别1,不新建类:{A,B,C,D,J,H,I}。可见,H由噪声点转变为了边界点。

接下来,以J为圆心,2为半径画圆,J为核心点,但J已经在类别1中且没有引入新点,故类别1保持不变。最后以K为圆心,2为半径画圆,K不是核心点也不是边界点,因此K为噪声点。

最终结果为:类别1,{A,B,C,D,J,H,I};类别2,{E、F、G};噪声点:K

4、代码实现

import numpy as np
from sklearn.cluster import DBSCAN
import matplotlib.pyplot as plt# 示例数据
X = np.array([[1, 1], [2, 1], [1, 3],  # 边界点和噪声点[8, 7], [8, 8], [9, 8], [10, 8],  # 簇C1[5, 5]  # 噪声点
])# 应用DBSCAN
dbscan = DBSCAN(eps=1.5, min_samples=2)
labels = dbscan.fit_predict(X)# 可视化
plt.figure(figsize=(8, 6))
plt.scatter(X[:, 0], X[:, 1], c=labels, cmap='viridis', s=100)
plt.title('DBSCAN聚类结果 (ε=1.5, MinPts=2)')
plt.grid(True)
plt.show()print("聚类标签:", labels)  # 输出: [ 0  0 -1  1  1  1  1 -1]
# -1表示噪声点,0和1表示两个不同的簇

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

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

相关文章

【C#】事务(进程 ID 64)与另一个进程被死锁在锁资源上,并且已被选作死锁牺牲品。请重新运行该事务。不能在具有唯一索引“XXX_Index”的对象“dbo.Test”中插入重复键的行。

🌹欢迎来到《小5讲堂》🌹 🌹这是《C#》系列文章,每篇文章将以博主理解的角度展开讲解。🌹 🌹温馨提示:博主能力有限,理解水平有限,若有不对之处望指正!&#…

LeetCode Hot 100 搜索二维矩阵

给你一个满足下述两条属性的 m x n 整数矩阵:每行中的整数从左到右按非严格递增顺序排列。每行的第一个整数大于前一行的最后一个整数。给你一个整数 target ,如果 target 在矩阵中,返回 true ;否则,返回 false 。示例…

python毕设高分案例:基于机器学习的抑郁症数据分析与预测系统,flask框架,算法包括XGboost模型、梯度提升树模型等

1 绪论 1.1 课题研究背景和意义 1.1.1 研究背景 在医疗行业不断发展的当下,数据量呈现出爆炸式增长,医学数据的复杂性和多样性也达到了前所未有的程度。电子病历系统记录了患者丰富的诊疗信息,医学影像技术如 CT、MRI 等生成海量的图像数据…

STM32与ADS1256多通道数据采样原理及控制程序

好的,使用 STM32 与 ADS1256 通信读取多通道电压是精密数据采集的常见方案。ADS1256 是一款高精度、24 位、8 通道(或差分 4 通道)的 ΔΣ ADC,非常适合需要高分辨率的应用(如传感器信号、医疗仪器等)。 以下是对整个过程的详细分析及基于 STM32 HAL 库的程序示例: 核…

Spring Boot 3.5.x 使用 SpringDoc 2 / Swagger3

这篇文章资料来自于网络,对部分知识整理,这里只是记录一下,仅供参考 为什么要用 Swagger Swagger 的核心思想是通过定义和描述 API 的规范、结构和交互方式,以提高 API 的可读性、可靠性和易用性,同时降低 API 开发的难…

@RefreshScope 核心原理深度解析:Spring Boot 的动态魔法

让我们通过全新的原理图解和代码级分析,揭开RefreshScope实现配置热更新的神秘面纱!一、工作原理全景图(优化版) #mermaid-svg-50lhLlOFeSRIWnLn {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px…

万字详解——OSI七层模型:网络通信的完整架构解析

OSI七层模型:网络通信的完整架构解析OSI(Open Systems Interconnection)七层模型是计算机网络领域最基础、最权威的参考框架。它由国际标准化组织(ISO)于1984年提出,旨在为不同厂商、不同技术的网络设备和系…

一个人开发一个App(OpenApi)

为了少写代码,统一前后端的网络层,我使用了OpenApi设计restful接口。然后用openapi-generator来生成flutter的代码。生成go代码用的是oapi-codegen,它对go更友好一些。 我们直接在api.yml中设计接口,所有的返回值与请求者都提取到components里…

光伏气象监测系统:助力光伏发电的智慧大脑

光伏气象监测系统:助力光伏发电的智慧大脑 柏峰【BF-GFQX】在全球积极推动能源转型、大力倡导 “双碳” 目标的当下,光伏发电凭借其清洁、可再生的显著优势,宛如一颗冉冉升起的新星,在能源领域迅速崭露头角,得以广泛推…

SpringCloud01——项目演变、微服务远程调用三种方式、springcloud介绍、nacos注册中心

目录 一、项目架构演变过程 1、单体应用架构 2、垂直应用架构 3、分布式服务架构 4、流动计算架构(SOA架构) 5、微服务架构 二、如何实现微服务远程调用 1、HttpClient工具类(springboot中) 形式1:调用第三方…

Oracle 和 MySQL 中的日期类型比较

Oracle 和 MySQL 都提供了多种日期和时间数据类型,但它们在实现和功能上有一些差异。以下是两者的主要日期类型对比:Oracle 日期类型DATE存储日期和时间(精确到秒)格式:YYYY-MM-DD HH24:MI:SS示例:TO_DATE(…

基于 Redis 实现共享 Session 登录的多种方法与实践

全文目录:开篇语**前言****1. 什么是共享 Session 登录?****2. 基于 Redis 实现共享 Session 的基本方法****2.1 通过 Redis 存储 Session 数据****2.1.1 基本流程****2.1.2 示例代码(Java Spring Boot Redis)****3. 使用 Redis…

spring cloud + easyRules 零基础搭建智能规则引擎

你是否曾想过在项目中嵌入一套轻量级且高度可扩展的规则引擎,轻松实现动态化的业务决策?在金融、电商、政务等领域,风险控制是业务安全的核心。传统硬编码方式很难应对复杂多变的风控需求,而规则引擎允许我们将这些规则独立出来&a…

AI应用:电路板设计

Diode Computers 公司 Diode Computers是一家专注于利用AI技术进行定制电路板设计和制造的公司,提供从概念到量产的全流程服务。其核心优势在于将电路板设计转化为AI可理解的代码形式,大幅提升设计效率并降低传统EDA工具的使用门槛 0。 核心服务 设计与制…

RocketMQ学习系列之——客户端消息确认机制

一、客户端使用MQ基本代码示例1、添加maven依赖<dependency><groupId>org.apache.rocketmq</groupId><artifactId>rocketmq-client</artifactId><version>5.3.0</version> </dependency>2、生产者代码示例public class Produc…

[leetcode] 组合总和

39. 组合总和 - 力扣&#xff08;LeetCode&#xff09; i class Solution {int aim;vector<vector<int>> ret;vector<int> path; public:vector<vector<int>> combinationSum(vector<int>& nums, int target) {aim target;dfs(nums…

新能源行业B端极简设计:碳中和目标下的交互轻量化实践

新能源行业B端极简设计&#xff1a;碳中和目标下的交互轻量化实践内容摘要在新能源行业&#xff0c;碳中和目标正推动着企业追求更高的运营效率和更低的资源消耗。然而&#xff0c;传统的B端交互设计往往复杂繁琐&#xff0c;不仅增加了用户的操作成本&#xff0c;还可能导致资…

减速机:自动化生产线的“精密传动心脏”

减速机作为自动化生产线的核心传动部件&#xff0c;通过调节转速与扭矩实现设备精准控制&#xff0c;其在自动化生产线中发挥着关键作用。以下是其具体应用方式&#xff1a;输送线驱动在自动化生产线中&#xff0c;输送线用于运输物料、半成品或成品&#xff0c;通过减速机可以…

从0到1学PHP(五):PHP 数组:高效存储与处理数据

目录一、数组的定义与分类1.1 索引数组1.2 关联数组1.3 多维数组二、数组的基本操作2.1 数组元素的添加、删除、修改和访问2.2 数组指针的操作三、数组处理函数3.1 数组排序函数3.2 数组统计函数3.3 数组过滤与转换函数一、数组的定义与分类 在 PHP 中&#xff0c;数组是一种非…

vscode 字体的跟换

打开vscode 左下角输入电脑中已经有的字体&#xff1a;有想要用的可以自己进行安装刷新这样就可改变了