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,口语优化新神器
- 上一篇
- Deepseek+GrammarlyGO,口语优化新神器
- 下一篇
- 百度网盘文件管理技巧与查找方法
-
- 文章 · python教程 | 39分钟前 |
- Python类型错误调试方法详解
- 129浏览 收藏
-
- 文章 · python教程 | 44分钟前 |
- 函数与方法有何不同?详解解析
- 405浏览 收藏
-
- 文章 · python教程 | 49分钟前 | docker Python Dockerfile 官方Python镜像 容器安装
- Docker安装Python步骤详解教程
- 391浏览 收藏
-
- 文章 · python教程 | 59分钟前 |
- DjangoJWT刷新策略与页面优化技巧
- 490浏览 收藏
-
- 文章 · python教程 | 1小时前 |
- pandas缺失值处理技巧与方法
- 408浏览 收藏
-
- 文章 · python教程 | 1小时前 |
- TF变量零初始化与优化器关系解析
- 427浏览 收藏
-
- 文章 · python教程 | 1小时前 |
- Python字符串与列表反转技巧
- 126浏览 收藏
-
- 文章 · python教程 | 1小时前 | Python 错误处理 AssertionError 生产环境 assert语句
- Python断言失败解决方法详解
- 133浏览 收藏
-
- 文章 · python教程 | 2小时前 |
- 动态设置NetCDF图表标题的实用方法
- 247浏览 收藏
-
- 文章 · python教程 | 2小时前 |
- PyCharm切换英文界面教程
- 405浏览 收藏
-
- 文章 · python教程 | 2小时前 |
- Behave教程:单个BDD示例运行方法
- 411浏览 收藏
-
- 文章 · python教程 | 3小时前 |
- PythonGTK3动态CSS技巧分享
- 497浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- ChatExcel酷表
- ChatExcel酷表是由北京大学团队打造的Excel聊天机器人,用自然语言操控表格,简化数据处理,告别繁琐操作,提升工作效率!适用于学生、上班族及政府人员。
- 3201次使用
-
- Any绘本
- 探索Any绘本(anypicturebook.com/zh),一款开源免费的AI绘本创作工具,基于Google Gemini与Flux AI模型,让您轻松创作个性化绘本。适用于家庭、教育、创作等多种场景,零门槛,高自由度,技术透明,本地可控。
- 3414次使用
-
- 可赞AI
- 可赞AI,AI驱动的办公可视化智能工具,助您轻松实现文本与可视化元素高效转化。无论是智能文档生成、多格式文本解析,还是一键生成专业图表、脑图、知识卡片,可赞AI都能让信息处理更清晰高效。覆盖数据汇报、会议纪要、内容营销等全场景,大幅提升办公效率,降低专业门槛,是您提升工作效率的得力助手。
- 3444次使用
-
- 星月写作
- 星月写作是国内首款聚焦中文网络小说创作的AI辅助工具,解决网文作者从构思到变现的全流程痛点。AI扫榜、专属模板、全链路适配,助力新人快速上手,资深作者效率倍增。
- 4552次使用
-
- MagicLight
- MagicLight.ai是全球首款叙事驱动型AI动画视频创作平台,专注于解决从故事想法到完整动画的全流程痛点。它通过自研AI模型,保障角色、风格、场景高度一致性,让零动画经验者也能高效产出专业级叙事内容。广泛适用于独立创作者、动画工作室、教育机构及企业营销,助您轻松实现创意落地与商业化。
- 3822次使用
-
- 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浏览

