Python数据聚类方法与K-means优化技巧
还在为Python数据聚类发愁?本文深入解析了常用的K-means算法及其优化技巧,助你玩转数据分析。K-means以其简洁高效著称,通过迭代将数据分配至最近簇中心并更新中心点,直至收敛。然而,它也存在对初始值敏感、需预设K值等局限性。本文详细介绍了如何通过n_init多次运行、k-means++初始化、肘部法则和轮廓系数法等策略优化K-means,并探讨了Mini-Batch K-Means、K-medoids、X-means等改进方法。此外,文章还介绍了DBSCAN、层次聚类和GMM等其他聚类算法,帮助你根据数据特征选择最合适的算法,提升聚类效果。无论你是初学者还是数据分析师,都能从中获得实用的技巧和启发。
K-means算法通过迭代将数据分配到最近的簇中心并更新中心,直至收敛;2. 优化策略包括使用n_init多次运行选择最优结果、k-means++初始化减少对初始值敏感、肘部法则和轮廓系数法确定K值;3. 局限性有对初始值和异常值敏感、需预设K值、假设簇为球形且密度均匀;4. 改进方法包括Mini-Batch K-Means加速计算、K-medoids提升鲁棒性、X-means自动选K、降维预处理提升效果;5. 其他聚类算法如DBSCAN可发现任意形状簇并识别噪声、层次聚类无需预设K且可可视化树状图、GMM提供概率性聚类更灵活;6. 实际应用中应根据数据特征选择合适算法,通常从K-means入手,效果不佳时尝试DBSCAN或GMM,结合多种方法优化聚类结果。
Python实现数据聚类,K-means是常用且直观的算法。它通过迭代将数据点分配到最近的簇中心,并更新中心点位置,直至收敛。优化K-means通常涉及初始中心选择、评估指标和变种算法,以克服其对初始值敏感、易陷入局部最优等局限性。
K-means算法,说实话,第一次接触时觉得它简单得有点粗暴,但正是这种直观性,让它在很多场景下都非常实用。不过,粗暴不代表没有技巧,它的优化空间可不小。
在Python中,我们通常会用到scikit-learn
库来实现K-means。它的使用非常简洁明了。核心思路就是:你告诉它想分成几类(K值),它就会帮你把数据点分好。
import numpy as np from sklearn.cluster import KMeans import matplotlib.pyplot as plt from sklearn.datasets import make_blobs # 生成一些示例数据 X, _ = make_blobs(n_samples=300, centers=4, cluster_std=0.60, random_state=0) # 初始化KMeans模型,设定簇的数量为4 # n_init='auto' (或一个整数) 告诉算法运行多少次不同的初始质心,并选择最好的结果,这本身就是一种优化 kmeans = KMeans(n_clusters=4, random_state=0, n_init='auto') # 拟合数据 kmeans.fit(X) # 获取聚类结果和簇中心 labels = kmeans.labels_ centroids = kmeans.cluster_centers_ # 可视化结果 plt.scatter(X[:, 0], X[:, 1], c=labels, s=50, cmap='viridis') plt.scatter(centroids[:, 0], centroids[:, 1], c='red', s=200, alpha=0.7, marker='X') plt.title('K-means Clustering') plt.xlabel('Feature 1') plt.ylabel('Feature 2') plt.show() print("簇中心点:\n", centroids)
这里面,n_init='auto'
(或者明确指定一个整数,比如n_init=10
)是一个很关键的优化点。它不是只跑一次K-means,而是会用不同的初始中心点跑多次,然后选一个总误差(惯性,inertia_)最小的结果。这大大降低了K-means陷入局部最优的风险。另外,init='k-means++'
是默认的初始化策略,它会选择距离尽可能远的初始中心点,这比随机选择要好得多,也是一个重要的内置优化。
如何选择K值?——K-means聚类中的“肘部法则”与轮廓系数法
K值,也就是聚类的簇数量,这玩意儿选不好,结果可能就差强人意。我个人感觉,这就像是给数据点找家,家分多了太散,分少了又挤,得有个合适的度。确定K值没有一个放之四海而皆准的“最佳”方法,但“肘部法则”和“轮廓系数法”是两种非常常用的经验性方法。
肘部法则 (Elbow Method)
它的核心思想是:随着K值的增加,每个簇内部的平方和(WCSS,Within-Cluster Sum of Squares,也就是inertia_
属性)会逐渐减小。当K值达到一个“恰到好处”的点时,WCSS的下降速度会显著放缓,这个点在图上看起来就像一个手肘。
wcss = [] # 尝试不同的K值 for i in range(1, 11): # 尝试从1到10个簇 kmeans = KMeans(n_clusters=i, random_state=0, n_init='auto') kmeans.fit(X) wcss.append(kmeans.inertia_) # inertia_ 就是WCSS plt.plot(range(1, 11), wcss) plt.title('Elbow Method') plt.xlabel('Number of Clusters (K)') plt.ylabel('WCSS') plt.show()
看上面这张图,你会发现WCSS一开始下降很快,然后逐渐平缓。那个“拐点”就是我们希望找到的K值。不过,有时候这个“肘部”并不那么明显,这确实让人有点头疼。
轮廓系数法 (Silhouette Score)
轮廓系数则提供了一个更量化的评估指标,它衡量了每个样本点与其所属簇的相似度(内聚性)以及与其他簇的相异度(分离性)。轮廓系数的取值范围是-1到1:
- 接近1:样本点与自身簇非常匹配,与其他簇相距很远。
- 接近0:样本点在两个簇的边界附近,可能分配不明确。
- 接近-1:样本点可能被错误地分配到错误的簇。
我们通常会选择使平均轮廓系数最大的K值。
from sklearn.metrics import silhouette_score silhouette_scores = [] # K值至少需要2个簇才能计算轮廓系数 for i in range(2, 11): kmeans = KMeans(n_clusters=i, random_state=0, n_init='auto') kmeans.fit(X) score = silhouette_score(X, kmeans.labels_) silhouette_scores.append(score) plt.plot(range(2, 11), silhouette_scores) plt.title('Silhouette Score Method') plt.xlabel('Number of Clusters (K)') plt.ylabel('Silhouette Score') plt.show() # 找到最佳K值 best_k = np.argmax(silhouette_scores) + 2 # 因为我们从K=2开始 print(f"根据轮廓系数法,最佳K值可能是:{best_k}")
我个人更偏爱轮廓系数,因为它提供了一个明确的数值,不像肘部法则那样需要“肉眼识别”。但两者结合使用,往往能得到更可靠的K值。
K-means算法的局限性与常见优化策略有哪些?
说句实在的,K-means虽然好用,但它也不是万能药。总有些时候,你会发现它的表现不尽如人意,甚至有些“脾气”。比如,你跑了几次,结果可能都不一样,这多半是初始中心点搞的鬼。
K-means的常见局限性:
- 对初始中心点敏感: 不同的初始质心可能导致不同的聚类结果,甚至陷入局部最优。虽然
k-means++
和n_init
能缓解,但无法完全消除。 - 需要预设K值: 这是最头疼的一点,很多时候我们对数据到底有几类是完全没概念的。
- 对异常值敏感: 少数远离大部分数据点的异常值可能会严重影响簇中心的位置,导致聚类结果偏差。
- 假设簇是球形的且大小相似: K-means使用欧氏距离,倾向于发现球形或凸形的簇。如果你的数据簇是任意形状(比如月牙形、环形),K-means的表现就会很差。
- 无法处理密度不均的簇: 如果不同簇的密度差异很大,K-means可能无法很好地分离它们。
针对这些局限性,除了前面提到的n_init
和k-means++
,我们还有一些常见的优化策略和替代方案:
- Mini-Batch K-Means: 当数据集非常大时,每次迭代都计算所有样本到所有质心的距离会非常耗时。Mini-Batch K-Means每次只使用数据的一个小批量(mini-batch)来更新簇中心,这大大加快了收敛速度,尤其适用于大数据集。它在
sklearn.cluster
中也有实现。 - K-medoids (K-中心点算法): 与K-means使用均值作为簇中心不同,K-medoids选择簇内的一个实际数据点作为中心点(medoid)。这使得它对异常值不那么敏感,因为medoid是数据集中真实存在的点,而不是计算出的平均值,但计算成本通常更高。
- X-means: 这是一种自动确定K值的算法。它在K-means的基础上,通过BIC(贝叶斯信息准则)来评估和分裂簇,从而找到一个相对最优的K值。这解决了K值预设的难题,但计算复杂度会增加。
- 使用其他距离度量: 对于特定类型的数据,欧氏距离可能不是最佳选择。例如,对于文本数据,余弦相似度可能更合适。虽然
sklearn
的K-means默认是欧氏距离,但理论上可以自定义距离函数(虽然实现起来会复杂些,通常需要自己编写K-means的迭代过程)。 - 降维预处理: 对于高维数据,先使用PCA(主成分分析)或t-SNE等降维技术,可以去除冗余信息、降低噪声,同时使数据在低维空间中更容易被K-means处理,有时还能提升聚类效果。
除了K-means,Python还有哪些强大的聚类算法?
有时候,K-means确实满足不了需求,比如你的数据形状很奇特,或者你压根不知道该分几类。这时候,就得请出其他“高手”了。我个人对DBSCAN情有独钟,因为它能找出那些不规则的“甜甜圈”形状的簇,这可是K-means的盲区。
1. DBSCAN (Density-Based Spatial Clustering of Applications with Noise)
DBSCAN是一种基于密度的聚类算法。它不需要预设簇的数量,能够发现任意形状的簇,并且能有效识别噪声点(异常值)。它的核心思想是:如果一个数据点周围足够密集,它就属于一个簇。
- 优点: 发现任意形状的簇;无需预设K值;能识别噪声。
- 缺点: 对参数
eps
(邻域半径)和min_samples
(最小样本数)敏感;对于密度差异较大的簇效果不佳。
from sklearn.cluster import DBSCAN from sklearn.preprocessing import StandardScaler # DBSCAN对特征缩放敏感,通常需要先进行标准化 X_scaled = StandardScaler().fit_transform(X) # eps: 邻域半径, min_samples: 形成核心点所需的最小样本数 dbscan = DBSCAN(eps=0.3, min_samples=5) clusters = dbscan.fit_predict(X_scaled) plt.scatter(X_scaled[:, 0], X_scaled[:, 1], c=clusters, s=50, cmap='viridis') plt.title('DBSCAN Clustering') plt.xlabel('Scaled Feature 1') plt.ylabel('Scaled Feature 2') plt.show() print("DBSCAN发现的簇标签:", np.unique(clusters)) # -1表示噪声点
2. 层次聚类 (Hierarchical Clustering / Agglomerative Clustering)
层次聚类构建了一个簇的层次结构。它可以是凝聚的(Agglomerative,从单个点开始,逐步合并最近的簇)或分裂的(Divisive,从一个大簇开始,逐步分裂)。最常用的是凝聚层次聚类。它不需要预设K值,你可以通过“剪切”树状图(dendrogram)来选择簇的数量。
- 优点: 不需要预设K值;可以生成树状图,便于理解簇的嵌套关系;能处理非球形簇。
- 缺点: 计算复杂度高(尤其对于大数据集);对噪声和异常值敏感。
from sklearn.cluster import AgglomerativeClustering from scipy.cluster.hierarchy import dendrogram, linkage # 生成一些新的数据,以便更好地展示层次聚类 X_hier, _ = make_blobs(n_samples=50, centers=3, cluster_std=0.8, random_state=42) # 凝聚层次聚类 # n_clusters=None 表示不预设簇的数量,可以后续通过linkage矩阵和dendrogram来确定 # linkage='ward' 是一种合并策略,尝试最小化合并后簇内方差的增加 agg_cluster = AgglomerativeClustering(n_clusters=3, linkage='ward') agg_labels = agg_cluster.fit_predict(X_hier) plt.scatter(X_hier[:, 0], X_hier[:, 1], c=agg_labels, s=50, cmap='viridis') plt.title('Agglomerative Clustering') plt.xlabel('Feature 1') plt.ylabel('Feature 2') plt.show() # 绘制树状图(需要scipy库) linked = linkage(X_hier, method='ward') plt.figure(figsize=(10, 7)) dendrogram(linked, orientation='top', distance_sort='descending', show_leaf_counts=True) plt.title('Dendrogram for Agglomerative Clustering') plt.xlabel('Sample Index') plt.ylabel('Distance') plt.show()
3. 高斯混合模型 (Gaussian Mixture Models, GMM)
GMM是一种概率模型,它假设数据点是由若干个高斯分布(正态分布)混合生成的。每个簇对应一个高斯分布。GMM不仅能给出每个点属于哪个簇,还能给出属于每个簇的概率,这比K-means的硬性划分要更灵活。
- 优点: 概率性聚类,提供每个点属于每个簇的概率;能处理非球形、大小不一的簇;对噪声相对不敏感。
- 缺点: 需要预设高斯分布的数量(类似于K值);对数据量较小或维度较高时可能不稳定;计算成本相对较高。
from sklearn.mixture import GaussianMixture # n_components 对应于簇的数量 gmm = GaussianMixture(n_components=4, random_state=0) gmm.fit(X) gmm_labels = gmm.predict(X) plt.scatter(X[:, 0], X[:, 1], c=gmm_labels, s=50, cmap='viridis') plt.title('Gaussian Mixture Model Clustering') plt.xlabel('Feature 1') plt.ylabel('Feature 2') plt.show() # 还可以获取每个样本属于每个簇的概率 # probabilities = gmm.predict_proba(X) # print("部分样本属于各簇的概率:\n", probabilities[:5])
选择哪种聚类算法,最终还是得看你的数据特点和具体需求。没有绝对的“最好”,只有最适合。我通常会先用K-means快速跑一下看看大概情况,如果效果不理想,再尝试DBSCAN或GMM。毕竟,数据科学很多时候就是一场不断尝试和优化的过程。
以上就是本文的全部内容了,是否有顺利帮助你解决问题?若是能给你带来学习上的帮助,请大家多多支持golang学习网!更多关于文章的相关知识,也可关注golang学习网公众号。

- 上一篇
- Deepseek+GrammarlyGO,口语优化新神器

- 下一篇
- 百度网盘文件管理技巧与查找方法
-
- 文章 · python教程 | 53分钟前 |
- Python实现KMeans聚类方法详解
- 469浏览 收藏
-
- 文章 · python教程 | 1小时前 | Python Python编程
- Python中文处理:jieba分词使用教程
- 128浏览 收藏
-
- 文章 · python教程 | 1小时前 | Python函数
- Python条件返回技巧分享
- 228浏览 收藏
-
- 文章 · python教程 | 2小时前 |
- Python中int是整数类型
- 258浏览 收藏
-
- 文章 · python教程 | 3小时前 |
- Python正则表达式编译与使用技巧
- 208浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 511次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 498次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 484次学习
-
- 千音漫语
- 千音漫语,北京熠声科技倾力打造的智能声音创作助手,提供AI配音、音视频翻译、语音识别、声音克隆等强大功能,助力有声书制作、视频创作、教育培训等领域,官网:https://qianyin123.com
- 206次使用
-
- MiniWork
- MiniWork是一款智能高效的AI工具平台,专为提升工作与学习效率而设计。整合文本处理、图像生成、营销策划及运营管理等多元AI工具,提供精准智能解决方案,让复杂工作简单高效。
- 209次使用
-
- NoCode
- NoCode (nocode.cn)是领先的无代码开发平台,通过拖放、AI对话等简单操作,助您快速创建各类应用、网站与管理系统。无需编程知识,轻松实现个人生活、商业经营、企业管理多场景需求,大幅降低开发门槛,高效低成本。
- 205次使用
-
- 达医智影
- 达医智影,阿里巴巴达摩院医疗AI创新力作。全球率先利用平扫CT实现“一扫多筛”,仅一次CT扫描即可高效识别多种癌症、急症及慢病,为疾病早期发现提供智能、精准的AI影像早筛解决方案。
- 212次使用
-
- 智慧芽Eureka
- 智慧芽Eureka,专为技术创新打造的AI Agent平台。深度理解专利、研发、生物医药、材料、科创等复杂场景,通过专家级AI Agent精准执行任务,智能化工作流解放70%生产力,让您专注核心创新。
- 230次使用
-
- Flask框架安装技巧:让你的开发更高效
- 2024-01-03 501浏览
-
- Django框架中的并发处理技巧
- 2024-01-22 501浏览
-
- 提升Python包下载速度的方法——正确配置pip的国内源
- 2024-01-17 501浏览
-
- Python与C++:哪个编程语言更适合初学者?
- 2024-03-25 501浏览
-
- 品牌建设技巧
- 2024-04-06 501浏览