K-means聚类模型算法的应用与原理

K-means聚类是一种非常流行的聚类算法,它的目标是将n个样本划分到k个簇中,使得每个样本属于与其最近的均值(即簇中心)对应的簇,从而使得簇内的方差最小化。K-means聚类算法简单、易于实现,并且在许多应用中都非常有效。

K-means算法的基本步骤:

  • 选择初始中心:随机选择k个样本点作为初始的簇中心,或者使用K-means++算法来更智能地选择初始簇中心。

  • 分配样本:将每个样本点分配到最近的簇中心,形成k个簇。

  • 更新簇中心:重新计算每个簇的中心,通常是簇内所有点的均值。

  • 迭代优化:重复步骤2和3,直到簇中心不再发生显著变化,或者达到预设的迭代次数。

  • 终止条件:当簇中心在连续迭代中的变化小于某个阈值,或者达到预设的最大迭代次数时,算法终止。

K-means算法的数学表示:

设 C={c1,c2,…,ck}C={c1​,c2​,…,ck​} 为簇中心的集合,X={x1,x2,…,xn}X={x1​,x2​,…,xn​} 为样本点集合。

K-means的目标是最小化簇内误差平方和(Within-Cluster Sum of Squares, WCSS):

J©=∑i=1k∑x∈Si∣∣x−ci∣∣2J©=∑i=1k​∑x∈Si​​∣∣x−ci​∣∣2

其中,SiSi​ 是簇 cici​ 中的样本点集合。

K-means算法的优缺点:

优点

  • 算法简单,易于理解和实现。
  • 在处理大数据集时,计算效率较高。
  • 可以用于发现任意形状的簇。

缺点

  • 需要预先指定k值,而k值的选择可能依赖于领域知识或试错。
  • 对初始簇中心的选择敏感,可能导致局部最优解。
  • 对噪声和异常点敏感,可能影响簇中心的计算。
  • 只能发现数值型特征的簇,不适合文本数据等非数值型数据。

K-means++算法:

K-means++是一种改进的K-means算法,用于更智能地选择初始簇中心,从而提高聚类的质量。K-means++的基本思想是:

  • 随机选择一个点作为第一个簇中心。
  • 对于每个剩余的点,计算其到最近簇中心的距离,并根据距离的平方选择下一个簇中心。
  • 重复步骤2,直到选择k个簇中心。

实际应用:

K-means聚类可以应用于多种场景,包括但不限于:

  • 市场细分:根据客户的特征将客户分组。
  • 图像分割:将图像分割成不同的区域或对象。
  • 社交网络分析:发现社交网络中的社区结构。
  • 文本聚类:对文档或新闻文章进行分组。

K-means聚类是一种非常实用的工具,但需要根据具体问题和数据集的特性来调整和优化。

下面是一个简单的Java实现K-means聚类算法的示例代码。这个示例将演示如何使用K-means算法对一组二维点进行聚类。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;public class KMeansClustering {static class Point {double x, y;Point(double x, double y) {this.x = x;this.y = y;}@Overridepublic String toString() {return String.format("(%f, %f)", x, y);}}public static void kMeans(List<Point> points, int k, int maxIterations) {Random rand = new Random();List<Point> centroids = new ArrayList<>();// 初始化质心for (int i = 0; i < k; i++) {centroids.add(points.get(rand.nextInt(points.size())));}for (int iter = 0; iter < maxIterations; iter++) {// 1. 将每个点分配到最近的质心List<List<Point>> clusters = new ArrayList<>();for (int i = 0; i < k; i++) {clusters.add(new ArrayList<>());}for (Point point : points) {double minDistance = Double.MAX_VALUE;int closestCentroid = 0;for (int j = 0; j < k; j++) {double dist = point.distance(centroids.get(j));if (dist < minDistance) {minDistance = dist;closestCentroid = j;}}clusters.get(closestCentroid).add(point);}// 2. 更新质心boolean changed = false;List<Point> newCentroids = new ArrayList<>();for (List<Point> cluster : clusters) {if (cluster.isEmpty()) {newCentroids.add(centroids.get(0)); // 如果某个簇为空,随机选择一个质心changed = true;} else {Point newCentroid = cluster.get(0);for (Point point : cluster) {newCentroid = new Point(newCentroid.x / cluster.size() + point.x / cluster.size(),newCentroid.y / cluster.size() + point.y / cluster.size());}newCentroids.add(newCentroid);}}// 检查质心是否变化,如果没有则停止迭代if (!changed && centroids.equals(newCentroids)) {break;}centroids.clear();centroids.addAll(newCentroids);}// 输出最终的质心和簇for (int i = 0; i < centroids.size(); i++) {System.out.println("Centroid " + i + ": " + centroids.get(i));System.out.print("Cluster " + i + ": ");for (Point point : clusters.get(i)) {System.out.print(point + " ");}System.out.println();}}public static void main(String[] args) {List<Point> points = new ArrayList<>();points.add(new Point(1.0, 2.0));points.add(new Point(1.5, 1.8));points.add(new Point(5.0, 8.0));points.add(new Point(8.0, 8.0));points.add(new Point(1.0, 0.6));points.add(new Point(9.0, 11.0));points.add(new Point(8.0, 2.0));points.add(new Point(10.0, 2.0));points.add(new Point(9.0, 3.0));int k = 3; // 簇的数量int maxIterations = 100; // 最大迭代次数kMeans(points, k, maxIterations);}
}

V哥来解释一下:

  • Point类:一个简单的Point类,包含x和y坐标,并重写了toString方法以便于打印。

  • kMeans方法:

    • 接受一组点、簇的数量k和最大迭代次数maxIterations作为参数。
    • 随机选择初始质心。
    • 进行迭代,每次迭代包括两个主要步骤:
      • 分配点到最近的质心:对于每个点,计算其到每个质心的距离,并将点分配到最近的质心所代表的簇。
      • 更新质心:计算每个簇所有点的均值,作为新的质心。
    • 如果质心没有变化,或者达到最大迭代次数,则停止迭代。
  • main方法:创建了一个点的列表,并指定了簇的数量和最大迭代次数,然后调用kMeans方法进行聚类。

这个示例代码演示了K-means聚类的基本实现,但它没有使用K-means++算法来选择初始质心,也没有处理空簇的情况。在实际应用中,可能需要根据具体问题进行相应的优化和改进。

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

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

相关文章

《MySQL索引》学习笔记

《MySQL索引》学习笔记 MySQL的体系结构存储引擎简介InnoDB简介MyISAM简介 索引索引结构BTreeHash索引思考索引分类 索引语法SQL性能分析索引使用最左前缀法则 索引失效的情况范围查询索引列运算字符串不加引号模糊查询or连接的条件数据分布影响 SQL提示覆盖索引前缀索引单列索…

Ubuntu安装Meatsploit2024.6.4

1、安装metasploit cd /opt && wget https://downloads.metasploit.com/data/releases/metasploit-latest-linux-x64-installer.run && wget https://downloads.metasploit.com/data/releases/metasploit-latest-linux-x64-installer.run.sha1 && echo…

操作系统复习-linux的进程管理

linux的进程管理 linux进程的相关概念 进程的类型 前台进程 前台进程就是具有终端&#xff0c;可以和用户交互的进程&#xff0c;会占用终端shell&#xff0c;不可以输入其他的命令。 后台进程 前台进程就是具有终端&#xff0c;可以和用户交互的进程。 不会占用终端shell&a…

macOS的word没有zotero怎么办

打开zotero,首选项,引用,重新安装加载项 然后到word里 点模板和加载项 把zotero勾上,OK了

Java学习【认识异常】

Java学习【认识异常】 认识异常异常的种类异常的作用 异常的处理方式JVM默认的处理方式捕获异常finally 多个异常的处理异常中的方法抛出异常 自定义异常 认识异常 在Java中&#xff0c;将程序执行过程中发生的不正常行为称为异常 异常的种类 Error代表的是系统级别的错误&a…

ClickHouse 使用技巧总结

文章目录 数据导入、导出技巧外部文件导入导技巧使用集成表引擎导入、导出数据 建表技巧表引擎选择技巧分区键选择技巧数据结构选择技巧分区技巧 高级技巧物化视图投影位图变更数据捕获 常见报错及处理方法 数据导入、导出技巧 外部文件导入导技巧 ClickHouse作为OLAP即席分析…

每日一题《leetcode--206.反转链表》

https://leetcode.cn/problems/reverse-linked-list/ 这道题可以定义一个新结点newhead&#xff0c;newhead指向NULL。此时遍历所给链表将遍历的每个结点头插到newhead上。 struct ListNode* reverseList(struct ListNode* head) {struct ListNode* curhead;struct ListNode* n…

Spring中的核心概念

黑马程序员SSM框架教程 文章目录 一、IoC二、DI三、目标&#xff1a;充分解耦 一、IoC IoC&#xff08;Inversion of Control&#xff09;控制反转 使用对象时&#xff0c;由主动new产生对象转换为外部提供对象&#xff0c;此过程中对象创建控制权由程序转移到外部&#xff0c…

Visual Studio 2022开发CTP的问题汇总

订阅合约的函数原型如下 virtual int SubscribeMarketData(char *ppInstrumentID[], int nCount) 0;参数定义 char* ppInstrumentID[] { "rb2410", "sc2407" }; 报错&#xff1a;E0144 “const char *” 类型的值不能用于初始化 “char *” 类型的实体 …

Go语言垃圾回收(GC原理)

1. GC回收机制 1.1 V1.3标记清除法 (1)概述 1.STW暂停 STW(暂停业务逻辑,找出可达和不可达对象) 2.对可达对象做上标记 标记完成之后,对象5和对象6不可达,被GC清除.之后STW结束. (2).缺点 STW :让程序暂停,程序出现卡顿.标记需要扫描整个heap.清除数据会产生heap碎片. 1.…

常用的linux命令

工作中常用的linux命令 查看磁盘存储情况 df -h查看端口占用情况 netstat -tunlp | grep 端口号查看java服务运行情况 ps -ef | grep "java"查看运行内存使用情况 free -h清除内存中的缓存 echo 3 > /proc/sys/vm/drop_caches查看linux系统最大进程数 ulim…

前端面试题日常练-day50 【面试题】

题目 希望这些选择题能够帮助您进行前端面试的准备&#xff0c;答案在文末 1. 在Bootstrap中&#xff0c;以下哪个类用于创建一个具有响应式的图片&#xff1f; a) .img-responsive b) .responsive-img c) .responsive-image d) .image-fluid 2. 哪个Bootstrap类用于创建一…

YYDS练手 130道python练习题 完整版PDF

近年来&#xff0c;Python在编程语言界里赚足了风头&#xff0c;无论是受欢迎程度&#xff0c;还是薪资待遇&#xff0c;都非常可观&#xff0c;相应的&#xff0c;Python岗位要求也越来越高&#xff0c;无论你是零基础还是老前辈&#xff0c;在Python面试中都不能轻视。 不打…

Spring Boot 系统学习第五天:Spring循环依赖实战经验

1 概述 本篇主要介绍使用依赖注入的一些实战经验。 2 把握Bean的作用域 前面说到Setter方法注入时&#xff0c;提到了Spring中的Bean作用域的概念。作用域描述了Bean在Spring IoC容器上下文中的生命周期和可见性。现在讨论Spring框架中不同类型的Bean作用域及其在使用上的指导…

Java 枚举类型深入解析

在Java中&#xff0c;枚举&#xff08;enum&#xff09;是一种特殊的数据类型&#xff0c;它允许一个变量是预定义的常量集合中的一个值。枚举类型在许多场景中都非常有用&#xff0c;比如定义一组明确的常量、简化代码的可读性和维护性等。本文将详细讲解Java中的枚举类型&…

对比WPF和Avalonia的边框渲染差异

众所周知&#xff0c;诸如Border、Rectangle等元素&#xff0c;是具有边框的。但在WPF和Avalonia中&#xff0c;边框的渲染机制有所不同。 如下代码&#xff0c;Border的边框和背景色均为黑色&#xff0c;并且将透明度设为0.5&#xff1a; <Border Width"100" H…

模拟实现C++vector

一&#xff1a;C库中对于vector的介绍 vector的底层其实就是数据结构中的顺序表&#xff0c;顺序表的底层就是变长数组&#xff0c;是一段连续的物理空间 在下面的实现中&#xff0c;重点实现的是其中的迭代器和插入删除&#xff0c;下标访问等功能&#xff0c;模拟实现模板类…

BottomSheetDialog高度自适应,布局RecyclerView使用问题

public class CultureBottomDialogView {/*** 标题*/private static TextView textTitle;/*** 关闭按钮*/private static TextView textClose;/*** 列表*/private static RecyclerView recyclerView;private static BottomDialogAdapter dialogAdapter;private static List<…

15-JavaScript 中的 `call`、`apply` 和 `bind`

JavaScript 中的 call、apply 和 bind 笔记分享 在 JavaScript 中&#xff0c;函数作为一等公民&#xff0c;可以像其他对象一样被操作。这种特性使得我们可以通过特定的方法来控制函数的调用环境&#xff08;即 this 的值&#xff09;。call、apply 和 bind 是三个常用的方法…

消息队列RabbitMQ

1. 消息队列概述 1.1 什么是消息队列 消息队列是一种用于在分布式系统中传递消息的数据结构。它采用先进先出&#xff08;FIFO&#xff0c;First In First Out&#xff09;的方式进行数据存储和管理。消息队列能够解耦生产者和消费者&#xff0c;从而实现系统的松散耦合&#…