K-means 聚类是一种无监督学习算法,它根据每个点到中心点的欧几里得距离对数据进行分组,称为 重心. 质心由同一簇中的所有点定义。 该算法首先选择随机点作为质心,然后迭代调整它们直到完全收敛。
使用 K-means 时要记住的重要一点是,集群的数量是一个超参数,它将在运行模型之前定义。
只需 3 行代码,即可使用 Scikit-Learn 实现 K-means。 Scikit-learn 也已经有可用的质心优化方法, 均值++,这有助于模型更快地收敛。
要应用 K-means 聚类算法,让我们加载 帕尔默企鹅 数据集,选择将被聚类的列,并使用 Seaborn 绘制带有颜色编码聚类的散点图。
备注: 你可以从这里下载数据集 链接.
让我们导入库并加载 Penguins 数据集,将其修剪为选定的列并删除缺少数据的行(只有 2 个):
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
df = pd.read_csv('penguins.csv')
print(df.shape)
df = df[['bill_length_mm', 'flipper_length_mm']]
df = df.dropna(axis=0)
我们可以使用 Elbow 方法来指示数据的集群。 它包括解释具有肘形的线图。 簇的数量是肘弯。 该图的 x 轴是聚类数,y 轴是每个聚类数的聚类内平方和 (WCSS):
wcss = []
for i in range(1, 11):
clustering = KMeans(n_clusters=i, init='k-means++', random_state=42)
clustering.fit(df)
wcss.append(clustering.inertia_)
ks = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
sns.lineplot(x = ks, y = wcss);
肘部方法表明我们的数据有 2 个聚类。 让我们绘制聚类前后的数据:
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(15,5))
sns.scatterplot(ax=axes[0], data=df, x='bill_length_mm', y='flipper_length_mm').set_title('Without clustering')
sns.scatterplot(ax=axes[1], data=df, x='bill_length_mm', y='flipper_length_mm', hue=clustering.labels_).set_title('Using the elbow method');
此示例显示了在用于选择聚类数量时,Elbow 方法如何仅作为参考。 我们已经知道数据集中有 3 种企鹅,但如果我们使用 Elbow 方法确定它们的数量,我们的结果将是 2 个聚类。
由于 K-means 对数据方差很敏感,让我们看一下我们正在聚类的列的描述性统计信息:
df.describe().T
结果是:
count mean std min 25% 50% 75% max
bill_length_mm 342.0 43.921930 5.459584 32.1 39.225 44.45 48.5 59.6
flipper_length_mm 342.0 200.915205 14.061714 172.0 190.000 197.00 213.0 231.0
请注意,平均值与标准差 (std) 相差甚远,这表明方差很大。 让我们尝试通过使用 Standard Scaler 缩放数据来减少它:
from sklearn.preprocessing import StandardScaler
ss = StandardScaler()
scaled = ss.fit_transform(df)
现在,让我们对缩放数据重复 Elbow 方法过程:
wcss_sc = []
for i in range(1, 11):
clustering_sc = KMeans(n_clusters=i, init='k-means++', random_state=42)
clustering_sc.fit(scaled)
wcss_sc.append(clustering_sc.inertia_)
ks = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
sns.lineplot(x = ks, y = wcss_sc);
查看我们的 Git 学习实践指南,其中包含最佳实践、行业认可的标准以及随附的备忘单。 停止谷歌搜索 Git 命令,实际上 学习 它!
这一次,建议的聚类数为 3。我们可以将带有聚类标签的数据与前两个图一起再次绘制以进行比较:
fig, axes = plt.subplots(nrows=1, ncols=3, figsize=(15,5))
sns.scatterplot(ax=axes[0], data=df, x='bill_length_mm', y='flipper_length_mm').set_title('Without cliustering')
sns.scatterplot(ax=axes[1], data=df, x='bill_length_mm', y='flipper_length_mm', hue=clustering.labels_).set_title('With the Elbow method')
sns.scatterplot(ax=axes[2], data=df, x='bill_length_mm', y='flipper_length_mm', hue=clustering_sc.labels_).set_title('With the Elbow method and scaled data');
使用 K-means 聚类时,需要预先确定聚类的数量。 正如我们在使用一种方法来选择我们的 k 集群的数量,结果只是一个建议,可能会受到数据方差量的影响。 进行深入分析并在聚类时生成多个具有不同 _k_s 的模型非常重要。
如果事先没有迹象表明数据中有多少聚类,请将其可视化、测试并解释它以查看聚类结果是否有意义。 如果没有,请再次集群。 此外,查看更多的一个指标并实例化不同的聚类模型——对于 K-means,查看轮廓分数,也许还有层次聚类,看看结果是否保持不变。