K-Means聚类算法是一种将数据点分组成K个簇的无监督学习算法。该算法通过迭代地移动簇中心(质心)来最小化簇内距离的总和。在本演示中,将使用Iris数据集来展示K-Means算法的效果,包括不同聚类数量和初始化方式对分类结果的影响。
在K-Means聚类中,选择正确的簇数量(K值)是非常重要的。如果将Iris数据集的聚类数量设置为3,算法将尝试将数据分为三个簇。这种设置通常更接近实际情况,因为Iris数据集实际上包含三种不同类型的鸢尾花。通过适当的聚类数量,可以更好地捕捉数据的内在结构。
K-Means算法的初始化方式对最终的聚类结果有显著影响。如果初始化不当,算法可能会陷入局部最优解,导致聚类效果不理想。在本例中,通过设置n_init参数为1(默认值为10),减少了算法使用不同质心种子运行的次数,从而展示了不良初始化对聚类过程的影响。可以看到,聚类结果可能会因为初始化的不同而有较大差异。
为了评估K-Means聚类算法的效果,需要与真实情况(Ground Truth)进行比较。在Iris数据集中,每朵鸢尾花的类别是已知的,这为提供了一个基准来衡量聚类算法的性能。通过将聚类结果与真实类别进行对比,可以评估算法的准确性和可靠性。
以下是使用Python和matplotlib库实现K-Means聚类算法并对Iris数据集进行可视化的代码示例。代码中展示了如何设置不同的聚类数量和初始化方式,以及如何绘制3D散点图来直观地展示聚类结果。
import matplotlib.pyplot as plt
import numpy as np
from sklearn import datasets
from sklearn.cluster import KMeans
# 加载Iris数据集
iris = datasets.load_iris()
X = iris.data
y = iris.target
# 定义不同的K-Means估计器
estimators = [
("k_means_iris_8", KMeans(n_clusters=8)),
("k_means_iris_3", KMeans(n_clusters=3)),
("k_means_iris_bad_init", KMeans(n_clusters=3, n_init=1, init="random")),
]
# 创建图形和子图
fig = plt.figure(figsize=(10, 8))
titles = ["8 clusters", "3 clusters", "3 clusters, bad initialization"]
# 绘制聚类结果
for idx, ((name, est), title) in enumerate(zip(estimators, titles)):
ax = fig.add_subplot(2, 2, idx + 1, projection="3d", elev=48, azim=134)
est.fit(X)
labels = est.labels_
ax.scatter(X[:, 3], X[:, 0], X[:, 2], c=labels.astype(float), edgecolor="k")
ax.set_xlabel("Petal width")
ax.set_ylabel("Sepal length")
ax.set_zlabel("Petal length")
ax.set_title(title)
# 绘制真实情况
ax = fig.add_subplot(2, 2, 4, projection="3d", elev=48, azim=134)
for name, label in [("Setosa", 0), ("Versicolour", 1), ("Virginica", 2)]:
ax.text3D(X[y == label, 3].mean(), X[y == label, 0].mean(), X[y == label, 2].mean() + 2, name, horizontalalignment="center", bbox=dict(alpha=0.2, edgecolor="w", facecolor="w"))
ax.scatter(X[:, 3], X[:, 0], X[:, 2], c=y, edgecolor="k")
ax.set_xlabel("Petal width")
ax.set_ylabel("Sepal length")
ax.set_zlabel("Petal length")
ax.set_title("Ground Truth")
# 调整子图间距并显示图形
plt.subplots_adjust(wspace=0.25, hspace=0.25)
plt.show()