当前位置: 首页 > news >正文

K-Means 聚类详解:算法原理 + 迭代过程图解 + C++ 实现 + 如何选 K(肘部法则)

一、引言

如果你手上只有一堆数据点,但没有任何标签,想让机器自己把相似的点归到一起,这就是「聚类」要做的事。K-Means 是无监督学习里最常用、也最容易讲清楚的聚类算法。本文从原理、两步迭代过程、完整可编译的 C++ 代码、复杂度,到「如何选 K」和算法局限,一次讲透。文中过程图来自码路星球的可视化演示(C++算法可视化,免费)。

二、算法原理:无监督聚类

K-Means 解决的问题是:给定 n 个二维点,把它们自动分成 k 组,使组内的点尽量靠近——事先不知道标签,所以是「无监督」。

它的全部精髓就是反复做两件事:

  1. 分配(Assignment):把每个点,分给离它最近的那个中心(按欧氏距离)。
  2. 更新(Update):把每个中心,移动到「分给它的那些点」的平均位置(质心)。

两步交替迭代,直到中心不再移动——聚类就稳定了。

三、分配 / 更新两步迭代图解

把演示里发生的事拆开看:

  • 初始化:放下 k 个簇中心(可视化里是菱形),所有点暂时是灰色、未分配。
  • 分配步:一个点一个点地,算它到各中心的距离,归到最近的中心并染上对应颜色——你能看到点逐个「选边站」。
  • 更新步:每个中心「滑」到自己那堆同色点的中间(质心)。
  • 然后再分配、再更新……几轮之后没有点再换簇、中心也不动,聚类完成。

为什么一定会收敛?每一步都在让「点到自己中心的总距离」变小(不会变大),而这个值有下界,所以一定会停下来。

四、完整可编译的 C++ 实现(带注释)

下面是核心骨架,对应演示里展示的kmeans流程,并补全成可直接编译运行的完整片段:

#include<bits/stdc++.h>usingnamespacestd;structPoint{doublex,y;intcluster=-1;};// 欧氏距离的平方(比较大小用平方即可,省一次开方)doubledist2(constPoint&a,constPoint&b){doubledx=a.x-b.x,dy=a.y-b.y;returndx*dx+dy*dy;}// 找离 p 最近的中心,返回其下标intnearest(constPoint&p,constvector<Point>&centers){intbest=0;doublebd=numeric_limits<double>::max();for(intj=0;j<(int)centers.size();j++){doubled=dist2(p,centers[j]);if(d<bd){bd=d;best=j;}}returnbest;}// 把第 j 个中心移到簇 j 的均值(质心);移动了返回 trueboolmoveToMean(Point&center,constvector<Point>&pts,intj){doublesx=0,sy=0;intcnt=0;for(constauto&p:pts)if(p.cluster==j){sx+=p.x;sy+=p.y;cnt++;}if(cnt==0)returnfalse;// 空簇:本轮不动(工程上需特殊处理)doublenx=sx/cnt,ny=sy/cnt;boolmoved=(nx!=center.x||ny!=center.y);center.x=nx;center.y=ny;returnmoved;}voidkmeans(vector<Point>&pts,vector<Point>&centers,intk){while(true){for(auto&p:pts)// ① 分配p.cluster=nearest(p,centers);// 归到最近的中心boolmoved=false;for(intj=0;j<k;j++)// ② 更新moved|=moveToMean(centers[j],pts,j);// 中心移到簇均值if(!moved)break;// 中心不动 → 收敛}}intmain(){vector<Point>pts={{60,60},{90,55},{270,60},{300,55},{60,232},{90,225},{270,232},{300,228}};vector<Point>centers={{120,55},{150,58},{180,55},{210,58}};// 4 个初始中心intk=(int)centers.size();kmeans(pts,centers,k);for(auto&p:pts)printf("(%.0f,%.0f) -> 簇 %d\n",p.x,p.y,p.cluster);return0;}

代码与演示里展示的核心循环一致:for (auto& p : pts) p.cluster = nearest(...)是分配,moved |= move(centers[j], mean(pts, j))是更新,if (!moved) break;是收敛判定。

五、复杂度分析

每轮迭代要算 n 个点到 k 个中心的距离,是O(n·k);跑 t 轮就是O(n·k·t)(n 点、k 簇、t 轮迭代)。空间O(n + k)。通常 t 不大,所以很快——这也是它流行的原因之一。

六、如何选 K(肘部法则)与局限

  • K 要你自己定:K-Means 不会告诉你该分几类。常用「肘部法则」——画出不同 k 对应的簇内误差,找误差下降明显放缓的「拐点」,就是合适的 k;也可用轮廓系数辅助。
  • 初始值敏感:初始中心选得不好,可能收敛到差的局部最优。工程上常随机多跑几次取最优,或用k-means++更聪明地选初始点。
  • 形状假设:它假设簇是「球形、大小相近」的。遇到环形、长条形的簇会失灵——那时考虑DBSCAN、谱聚类。
  • 量纲问题:不同特征量纲差太多(比如「年龄 0-100」和「收入 0-100万」),距离会被大尺度特征主导,先做归一化

七、小结

K-Means = 分配 + 更新两步交替,迭代到收敛;复杂度 O(n·k·t),简单高效;关键在于选对 K、处理好初始化、注意球形假设和归一化。把这两步「画出来」看,比读十遍公式都直观。本文的过程图来自码路星球的 C++ 算法可视化:(我不慌----成长杂货铺:https://wobuhuang.com)

http://www.jsqmd.com/news/989881/

相关文章:

  • 2026年热门的济南别墅螺杆电梯/螺杆电梯/螺杆电缸高口碑品牌推荐 - 行业平台推荐
  • 2026年旋转楼梯行业口碑观察:陕西及周边市场靠谱品牌技术特征与选型指南 - 优质品牌商家
  • AltStore:无需越狱的iOS第三方应用商店终极指南
  • 3个命令搞定iOS应用包下载:ipatool实战指南
  • 浙江智能柜行业专业能力分析与主要供应商评估(2026) - 优质品牌商家
  • 从《硬件软件接口》到可运行的RISC-V核:我的五级流水线学习笔记与避坑指南
  • 3个技巧快速配置Obsidian美化:新手极速上手完整指南
  • 2026年靠谱的机器人零件加工/昆山五轴零件加工多家厂家对比分析 - 品牌宣传支持者
  • 告别Google语音识别!用App Inventor 2 + 讯飞引擎,手把手教你做个能听懂中文的语音机器人
  • 期货合约临近交割怎么预警:天勤 expire_datetime 与禁开逻辑
  • 贪心算法实战:用C++搞定活动安排、最优装载和Dijkstra最短路径(附完整可运行代码)
  • ZYNQ-7010裸机环境下的触摸LCD驱动与绘图示例工程(含HDF+SDK源码)
  • 2026年知名的贵州发酵饲料/贵州富硒肉/贵州富硒饲料厂家推荐与选型指南 - 行业平台推荐
  • 数据的加密与解密(04:05)
  • STM32F103的RTC只有秒计数器?别慌,手把手教你用Unix时间戳实现完整日历(含CubeMX配置)
  • 数据的加密与解密(04:07)
  • 2026年靠谱的宿州税务规划/宿州财务外包/宿州资质办理正规公司推荐 - 品牌宣传支持者
  • 终极指南:3步打造你的专属Minecraft电影级光影世界
  • 2026年 混合机厂家最新推荐榜:不锈钢混合机/高速混合机/三维混合机/粉体混合机/干粉混合机/液体混合机源头工厂优选指南 - 品牌发掘
  • Vim 零基础核心基础篇
  • 豫北工科院校发展观察:河南机电高等专科学校及同类院校的多维比较分析 - 优质品牌商家
  • 误删照片怎么办?用PhotoRec数据恢复工具找回珍贵记忆
  • Bottles终极指南:在Linux上轻松运行Windows软件的完整解决方案
  • 从‘样品管理’到‘报告生成’:一个真实业务场景下的poi-tl附件插入实战
  • 萧山优秀的杭州喷涂设备:杭州及周边喷涂加工企业能力分析与行业指南 - 优质品牌商家
  • WebAuthn + Passkey:无密码认证新时代
  • GetQzonehistory:3步轻松备份你的QQ空间青春记忆
  • 玩转本地自动化 AI:OpenClaw 多系统部署与常见问题排查
  • 如何解决国内访问GitHub缓慢问题:Fast-GitHub完整使用指南
  • 2026年热门的拆除食品设备/二手食品设备/转让食品设备/出售食品设备长期合作厂家推荐 - 品牌宣传支持者