机器学习(八):K-Means聚类原理与实战

news2025/4/25 11:42:03

声明:未经允许禁止转载与抄袭。

前言

k k k均值( k k k-means)聚类算法是一种经典的无监督聚类算法,本文将深入解析其理论原理,并在真是数据集上进行算法实践,话不多说,请看下文。

算法原理

给定样本集 D = { x 1 , x 2 , … , x m } D=\left\{\mathbf{x}_1, \mathbf{x}_2, \ldots, \mathbf{x}_m\right\} D={x1,x2,,xm},其中每个样本 x i \mathbf{x}_i xi都由一个向量表示,例如以周志华老师西瓜书中的西瓜数据集为例,每个样本都包含两个属性密度和含糖量,这两个属性值组成的向量便是该样本的向量表示。

k k k均值算法旨在将样本集 D D D划分为 k k k个簇,即 C = { C 1 , C 2 , … , C k } C=\left\{C_1,C_2,\ldots,C_k\right\} C={C1,C2,,Ck},使得每个样本都被划分到与其距离最小的簇中。用数学来刻画就是, k k k均值算法希望能够最小化所划分的 k k k个簇的平方误差,即:
argmin C ∑ i = 1 k ∑ x ∈ C i ∥ x − μ i ∥ 2 2 \text{argmin}_{C} \sum_{i=1}^k \sum_{\mathbf{x} \in C_i}\left\|\mathbf{x}-\mathbf{\mu}_i\right\|_2^2 argminCi=1kxCixμi22

其中 μ i = 1 ∣ C i ∣ ∑ x ∈ C i x \boldsymbol{\mu}_i=\frac{1}{\left|C_i\right|} \sum_{\mathbf{x} \in C_{\boldsymbol{i}}} \mathbf{x} μi=Ci1xCix 表示簇 C i C_i Ci 的均值向量, x \mathbf{x} x表示簇 C i C_i Ci中的样本。

k k k均值算法事先设定数据集 D D D要划分为 k k k个簇,初始化时,会先从数据集 D D D中随机挑选 k k k个样本作为各个簇的初始均值向量(簇中心)。然后遍历所有样本,分别计算各个样本与各个簇中心的距离,并将样本划分到与距离最小的簇中。待到所有样本都划分完毕后,将各个簇样本向量的均值向量作为新的簇均值向量,重复上述的步骤,直到上一轮所有的簇中心均值向量与本轮计算的结果相同为止。该算法的具体算法流程如下:

kmeans-algo

需要注意的是,实际计算过程中为避免计算时间过长,该算法的终止条件不可能这样严苛。西瓜书中给出了两种方案:

  • 设置一个最大轮数。
  • 设置均值向量的变化阈值,若新簇中心与旧簇中心之间的距离不超过该阈值即可,而不是严格不变。

对于 k k k均值聚类算法而言,数据集的预处理和 k k k值的选取同样十分重要,可以参考博客【机器学习】K-means(非常详细),限于篇幅原因,本文就不详细展开。

算法实践

本文在鸢尾花数据集上进行 k k k均值聚簇算法的实践。

基于最大轮数终止 k k k均值聚类算法实现如下所示,两个向量之间的距离计算本文采用了余弦距离

import numpy as np
from scipy.spatial.distance import cdist


class KMeansModel:
    def rand_pick(self, x, k):
        """
        随机选取k个簇中心
        """
        n = x.shape[0]
        indices = np.random.choice(n, k, replace=False)
        return x[indices]

    def calculate_distance(self, x, centers):
        """
        计算簇中心与数据样本之间的余弦距离
        centers: 簇中心数据 (k, d)
        x: 样本 (N, d)
        """
        return cdist(x, centers, metric="cosine")

    def get_centers(self, k, x, y):
        """
        根据计算结果重新计算簇中心
        y: 根据距离将数据集划分的标签数组 (N)
        """
        centers = np.zeros((k, x.shape[1]))
        for label in range(k):
            centers[label] = np.mean(x[y == label], axis=0)
        return centers

    def get_label(self, dis):
        """
        根据距离矩阵将每个样本划分到距离最小的簇中心
        """
        return np.argmin(dis, axis=-1)

    def cluster(self, x, k, times):
        """
        进行KMeans聚类
        x: 数据样本 (N, d)
        k: 类别数
        tims: 迭代次数
        """
        # 随机选取k个作为初始簇中心
        centers = self.rand_pick(x, k)
        for _ in range(times):
            # 计算各个样本到簇中心的距离
            dis = self.calculate_distance(x, centers)
            # 根据距离矩阵将样本进行划分
            y = self.get_label(dis)
            # 重新计算新的簇中心
            centers = self.get_centers(k, x, y)
        return y

在鸢尾花数据集上,设置的实验参数为 k = 3 k=3 k=3 t i m e s = 500 times=500 times=500,即将整个数据集聚为 3 3 3个簇,算法迭代 500 500 500轮终止。

算法额外对比了基于sklearn库实现的 k k k均值聚簇算法的效果,为更直观的展示,本文对数据集进行PCA降维,下图从左到右分别是真实标签、本文模型的聚类结果、基于sklearn算法的聚类结果。从结果可以看出,本文实现的模型在鸢尾花数据集上效果还是不错的。

kmeans-vis

结语

以上便是本文的全部内容,如果感觉不错可以支持一下,若有任何问题敬请批评指正。

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

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

相关文章

【stm32--HAL库DMA+USART+空闲中断不定长收发数据】

串口通信-Hal库实现不定长度收发,DMAUSART DMA串口STM32CUBEMX配置(工程创建)基础配置时钟配置工程配置 代码编写现象 DMA 在正式配置之前,我们先来一起简单了解一下DMA。DMA(Direct Memory Access,直接内…

【SPP】蓝牙串口配置中LM互操作性要求深度解析

在蓝牙协议栈中,链路管理器(Link Manager, LM)承担着链路建立、安全管理、功耗控制等核心功能。对于串行端口配置文件(SPP)而言,LM 的互操作性直接影响连接稳定性、数据安全性和设备功耗。本文基于蓝牙核心…

Java迭代器【设计模式之迭代器模式】

目录 一.前言 二.正文 1.我写的类为什么不能使用增强for(迭代器遍历) 2.代码健全性——迭代器常见的两个Exception 1.NoSuchElementException 2.ConcurrentModificationException 三.后言 一.前言 本篇面向对象主要为和我一样的小白,主要是对迭代器模式的浅…

Eclipse IDE

创建新的Java项目和类 在 Eclipse IDE 中创建一个新的 Java 项目和 Java 类的步骤如下: 1. 创建新的 Java 项目 打开 Eclipse IDE。在菜单栏中,点击 File > New > Java Project。在弹出的对话框中,输入项目名称(例如&…

计算机视觉算法实战——基于YOLOv8的自动驾驶障碍物实时感知系统

✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连✨ ​​​ ​​​​​​​​​ ​​ 引言:自动驾驶感知系统的关键挑战 自动驾驶技术正以前所未有的速度重塑交通出行方式&#xff…

【boost搜索引擎】下

boost搜索引擎 1. 编写搜索引擎模块 Searcher2. 编写 http_server 模块3. 编写前端模块4. 添加日志5. 补充 去掉暂停词6. 项目扩展方向 1. 编写搜索引擎模块 Searcher 这一模块主要提供建立索引,以及收到用户的发起的http请求通过Get方法提交的搜索关键字&#xff…

数据结构优化DP总结

单调栈:Codeforces Round 622 (Div. 2) C2. Skyscrapers (hard version) 简单来讲就是最后需要呈现出一个单峰数组,使得总高度最高。 最开始想到暴力枚举每一个元素都充当最高的“单峰”,但是这里的 n 过大,这样枚举肯定会TLE。 …

[Linux系统编程]进程间通信—system V

进程间通信—system V 1. System V 共享内存(Shared Memory)1.1 共享内存的建立过程1.2 共享内存函数2. System V 消息队列(Message Queues)3. System V 信号量(Semaphores)4. 总结前言: 之前所提的管道通信是基于文件的,OS没有做过多的设计工作。 system V 进程间通信…

第十四届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组(部分题解)

文章目录 前言日期统计题意: 冶炼金属题意: 岛屿个数题意: 子串简写题意: 整数删除题意: 总结 前言 一年一度的🏀杯马上就要开始了,为了取得更好的成绩,好名字写了下前年2023年蓝桥…

分析sys高问题的方法总结

一、背景 sys高的问题往往属于底层同学更需要关注的问题,sys高的问题往往表现为几种情况,一种是瞬间的彪高,一种是持续的彪高。这篇博客里,我们总结一下常用的分析方法和分析工具的使用来排查这类sys高的问题。 二、通过mpstat配…

智谱发布AI Agent“AutoGLM沉思”,开启AI“边想边干”新时代

近日,智谱正式推出全新AI Agent产品——AutoGLM沉思,标志着人工智能从“思考”迈向“执行”的关键突破。该智能体不仅具备深度研究能力,还能自主完成实际操作,真正实现“边想边干”的智能化应用。 在演示环节,智谱展示…

使用Leaflet对的SpringBoot天地图路径规划可视化实践-以黄花机场到橘子洲景区为例

目录 前言 一、路径规划需求 1、需求背景 2、技术选型 3、功能简述 二、Leaflet前端可视化 1、内容布局 2、路线展示 3、转折路线展示 三、总结 前言 在当今数字化与智能化快速发展的时代,路径规划技术已经成为现代交通管理、旅游服务以及城市规划等领域的…

【小兔鲜】day02 Pinia、项目起步、Layout

【小兔鲜】day02 Pinia、项目起步、Layout 1. Pinia2. 添加Pinia到Vue项目3. 案例:Pinia-counter基础使用3.1 Store 是什么?3.2 应该在什么时候使用 Store? 4. Pinia-getters和异步action4.1 getters4.2 action如何实现异步 1. Pinia Pinia 是 Vue 的专…

PyTorch 激活函数

激活函数是神经网络中至关重要的组成部分,它们为网络引入了非线性特性,使得神经网络能够学习复杂模式。PyTorch 提供了多种常用的激活函数实现。 常用激活函数 1. ReLU (Rectified Linear Unit) 数学表达式: PyTorch实现: torch.nn.ReLU(inplaceFals…

魔塔社区使用llamafactory微调AI阅卷试题系统

启动 LLaMA-Factory 1. 安装 LLaMA-Factory 执行安装指令 git clone --depth 1 https://github.com/hiyouga/LLaMA-Factory.git cd LLaMA-Factory pip install -e ".[torch,metrics]"解决依赖冲突 如果遇到依赖冲突,可使用以下命令安装,不…

如何在 Unity3D 导入 Spine 动画

一、前言 《如何在 Unity3D 项目中导入 Spine 动画》,虽然在网上有很多这种文章,直接将问题交给 DeepSeek 也能得到具体的操作流程,但是照着他们提供的方法还是能遇到几个问题,比如: AI 回答没有提到 Unity 无法识别.…

论文笔记:ASTTN模型

研究现状 现有研究大多通过分别考虑空间相关性和时间相关性或在滑动时间窗口内对这种时空相关性进行建模,而未能对直接的时空相关性进行建模。受最近图领域Transformer成功的启发,该模型提出利用局部多头自关注,在自适应时空图上直接建立跨时…

2025-4-2 蓝桥杯刷题情况(分布式队列)

1.题目描述 小蓝最近学习了一种神奇的队列:分布式队列。简单来说,分布式队列包含 N 个节点(编号为0至N-1,其中0号为主节点),其中只有一个主节点,其余为副节点。 主/副节点中都各自维护着一个队列,当往分布式队列中添加…

【Java中级】10章、内部类、局部内部类、匿名内部类、成员内部类、静态内部类的基本语法和细节讲解配套例题巩固理解【5】

❤️ 【内部类】干货满满,本章内容有点难理解,需要明白类的实例化,学完本篇文章你会对内部类有个清晰的认知 💕 内容涉及内部类的介绍、局部内部类、匿名内部类(重点)、成员内部类、静态内部类 🌈 跟着B站一位老师学习…

swift-7-汇编分析闭包本质

一、汇编分析 fn1里面存放的东西 func testClosure2() {class Person {var age: Int 10}typealias Fn (Int) -> Intvar num 0func plus(_ i: Int) -> Int {num ireturn num}return plus} // 返回的plus和num形成了闭包var fn1 getFn()print(fn1(1)) // 1print(fn1(…