导语:
欢迎来到“聚类算法”的世界!前面我们大概举例说明了一下无监督算法中的聚类算法,现在我们就来正式探索一下什么叫聚类,聚类分析是无监督学习中的一颗璀璨明珠,它不需要标签,就能帮助我们识别数据的内在结构,像一位侦探,揭示不同数据点之间的神秘联系。今天,我们将一起深入了解常见的聚类算法——K-Means和层次聚类,带着具体的实战示例走进Kaggle,看看这些算法如何帮助我们解决实际问题!
1. K-Means 聚类算法
1.1 什么是 K-Means?
K-Means 是一种经典的聚类算法,目的是把数据分成 K 个相似的“簇”(clusters)。每个簇中包含的样本,尽量使得簇内数据点之间的相似度最大,簇与簇之间的差异最大。通俗点说,K-Means 就是将你的数据点分到 K 个小团体里,每个团体内的成员看起来很相似,而不同团体的成员看起来很不一样。
1.2 K-Means 算法步骤
- 选择初始中心点:随机选择 K 个点作为初始聚类中心。
- 分配数据点:每个数据点会被分配给离自己最近的聚类中心。
- 更新聚类中心:每个簇的中心点更新为该簇中所有点的均值。
- 重复步骤 2 和 3,直到聚类中心不再变化或者达到预设的迭代次数。
1.3 初始中心点选择的影响
初始中心点的选择对算法的结果有很大影响。若选择不合理,可能会导致算法陷入局部最优解,甚至可能出现聚类效果很差的情况。为了解决这个问题,我们通常使用 K-Means++ 来优化初始点的选择。
1.4 收敛条件
K-Means 算法的收敛条件是,当聚类中心不再发生变化,或者变化非常小,达到预设的阈值时,算法就结束了。此时,数据的分类结果也算是确定了。
2. 聚类评估指标
聚类分析不像监督学习那样有标签可供评估,那么我们如何知道聚类效果好不好呢?这时,聚类评估指标就派上了用场。常用的评估指标之一是 轮廓系数(Silhouette Coefficient)。
2.1 轮廓系数(Silhouette Coefficient)
轮廓系数是用来衡量一个数据点在其聚类中的表现是否合理的指标。它的取值范围是从 -1 到 1:
- 接近 1:数据点非常适合当前簇,且与其他簇相距较远。
- 接近 0:数据点位于两个簇之间,难以归属某一个簇。
- 接近 -1:数据点应该属于其他簇。
轮廓系数越大,说明聚类效果越好。计算方式:
S ( i ) = b ( i ) − a ( i ) m a x ( a ( i ) , b ( i ) ) S(i) = \frac{b(i) - a(i)}{max(a(i), b(i))} S(i)=max(a(i),b(i))b(i)−a(i)
其中, a ( i ) a(i) a(i) 是数据点 i i i 到同簇内其他点的平均距离, b ( i ) b(i) b(i) 是数据点 i i i 到最近簇的平均距离。
3. 层次聚类算法
3.1 什么是层次聚类?
层次聚类是一种通过逐步合并(凝聚式)或拆分(分裂式)簇的方式来进行聚类的算法。其目标是创建一个聚类树(又叫树状图),可以直观地看到数据的聚类层次结构。
3.2 凝聚式层次聚类(Agglomerative Clustering)
凝聚式聚类从每个数据点开始,将每个数据点当作一个簇。然后,逐步合并距离最小的簇,直到所有数据点都在一个簇内,或者达到预设的簇数为止。
3.3 分裂式层次聚类(Divisive Clustering)
分裂式聚类的过程与凝聚式相反。它从整个数据集开始,逐步将其拆分为更小的簇,直到每个簇只包含一个数据点。
3.4 凝聚式与分裂式层次聚类的区别
- 凝聚式聚类:从小的簇合并成大的簇,适合数据量较小的情况,且计算复杂度较高。
- 分裂式聚类:从大的簇拆分成小的簇,适合数据量较大的情况,但不常用,因为其计算复杂度也较高。
K-Means 实战示例
现在,我们来一个具体的例子,使用 Kaggle 上的 Wine Quality 数据集 来演示如何使用 K-Means 算法进行聚类分析,Wine Quality 数据集 在我之前的文章中有具体的数据,大家可以翻一翻下载下来作为练习使用。
代码实现:
# 导入所需库
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler# 加载数据集
data = pd.read_csv('winequality.csv')
X = data[['alcohol', 'total acidity']]# 统一尺度,标准化数据
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)# K-Means 聚类
kmeans = KMeans(n_clusters=3, init='k-means++', max_iter=300, n_init=10, random_state=0)
y_kmeans = kmeans.fit_predict(X_scaled)plt.scatter(X_scaled[y_kmeans == 0, 0], X_scaled[y_kmeans == 0, 1], s=100, c='red', label='Cluster 1')
plt.scatter(X_scaled[y_kmeans == 1, 0], X_scaled[y_kmeans == 1, 1], s=100, c='blue', label='Cluster 2')
plt.scatter(X_scaled[y_kmeans == 2, 0], X_scaled[y_kmeans == 2, 1], s=100, c='green', label='Cluster 3')
plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1], s=300, c='yellow', label='Centroids')
plt.title('K-Means Clustering of Wine Quality')
plt.xlabel('Alcohol Content')
plt.ylabel('Total Acidity')
plt.legend()
plt.show()# 计算轮廓系数
silhouette_avg = silhouette_score(X, y_kmeans)
print(f"Silhouette Coefficient: {silhouette_avg}")
输出:
Silhouette Coefficient: 0.553819
一个较高的轮廓系数意味着聚类效果较好,在这个例子中,我们的聚类结果是非常不错的!
在上面的例子中,你如果无法确定k值,可以画肘图,利用肘部法则来确定具体的k值,如果不太熟悉肘部法则的可以翻看我上一篇的博客,里面有详细的讲解。
接下来我们再分别利用凝聚式与分裂式层次聚类来进行建模,加深打架对于凝聚式和分裂式层次聚类的理解。
凝聚式层次聚类建模
# 导入新的库
from scipy.cluster.hierarchy import dendrogram, linkage# 计算凝聚式层次聚类
Z = linkage(X_scaled, 'ward')# 绘制树形图(谱系图)来展示聚类过程
plt.figure(figsize=(10, 5))
dendrogram(Z)
plt.title('Agglomerative Hierarchical Clustering Dendrogram')
plt.xlabel('Data Points')
plt.ylabel('Distance')
plt.show()
分裂式层次聚类建模
分裂式层次聚类在 Python 中没有像凝聚式那样直接可用的简单函数,这里我们用scikit-learn-extra库来实现一个简单的示例(需先安装scikit-learn-extra库)。
from sklextra.cluster import DivisiveHierarchicalClustering
# 创建分裂式层次聚类模型,设置分成3类
model = DivisiveHierarchicalClustering(n_clusters=3)
y_divisive = model.fit_predict(X_scaled)# 可视化分裂式层次聚类结果
plt.scatter(X_scaled[y_divisive == 0, 0], X_scaled[y_divisive == 0, 1], s=100, c='red', label='Cluster 1')
plt.scatter(X_scaled[y_divisive == 1, 0], X_scaled[y_divisive == 1, 1], s=100, c='blue', label='Cluster 2')
plt.scatter(X_scaled[y_divisive == 2, 0], X_scaled[y_divisive == 2, 1], s=100, c='green', label='Cluster 3')
plt.title('Divisive Hierarchical Clustering of Wine Quality')
plt.xlabel('Alcohol Content')
plt.ylabel('Total Acidity')
plt.legend()
plt.show()
总结:
聚类算法,尤其是 K-Means 和层次聚类,是无监督学习中非常实用的工具。通过这些方法,我们可以在没有标签的情况下对数据进行合理的分组。在实际应用中,K-Means 更常用,因为其计算速度较快,而层次聚类则适合用于较小规模的数据集。
希望你通过这篇文章了解了聚类算法的基本原理,并且通过具体的代码示例,能够更深入地掌握它的使用技巧。别忘了,聚类不仅仅是一个数学模型,它还能帮助你发现数据中潜藏的有趣模式!
各位道友功力日渐深厚,快新年了,祝愿各位道友在新的一年都能心想事成!
如果大家还是对聚类算法的图形生成情况有疑问,感觉理解的不太直观,这里我给大家推荐一个聚类算法可视化平台:https://www.naftaliharris.com/blog/visualizing-k-means-clustering/
这是国外大佬 Naftali所建立的一个网站,容易理解,里面包含常用的聚类算法图形,可以自己选择k值和聚类中心,观看聚类过程。