层次聚类是一种常用的数据聚类方法,它可以在没有预设类别数量的情况下,根据数据点之间的距离进行聚类。本文将介绍如何在瑞士卷数据集上应用层次聚类算法,包括无结构和有结构的聚类方法。瑞士卷数据集是一个非线性的三维数据集,常用于测试聚类算法的性能。
在无结构层次聚类中,不考虑数据点之间的连接性约束,仅根据距离进行聚类。这种方法可能会在瑞士卷的不同折叠处形成跨越的聚类,从而破坏了数据集的结构。以下是使用Python进行无结构层次聚类的代码示例:
from sklearn.datasets import make_swiss_roll
from sklearn.cluster import AgglomerativeClustering
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# 生成瑞士卷数据集
n_samples = 1500
noise = 0.05
X, _ = make_swiss_roll(n_samples, noise=noise)
X[:, 1] *= 0.5 # 使数据集更细长
# 执行无结构层次聚类
print("执行无结构层次聚类...")
st = time.time()
ward = AgglomerativeClustering(n_clusters=6, linkage="ward")
ward.fit(X)
elapsed_time = time.time() - st
label = ward.labels_
print(f"耗时:{elapsed_time:.2f}秒")
print(f"数据点数量:{label.size}")
# 绘制无结构层次聚类结果
fig1 = plt.figure()
ax1 = fig1.add_subplot(111, projection="3d", elev=7, azim=-80)
ax1.set_position([0, 0, 0.95, 1])
for l in np.unique(label):
ax1.scatter(X[label == l, 0], X[label == l, 1], X[label == l, 2],
color=plt.cm.jet(float(l) / np.max(label + 1)), s=20, edgecolor="k")
plt.suptitle(f"无连接性约束(耗时{elapsed_time:.2f}秒)")
在上述代码中,首先生成了瑞士卷数据集,然后使用AgglomerativeClustering类进行无结构层次聚类。最后,使用matplotlib库绘制了聚类结果。可以看到,无结构聚类在瑞士卷的不同折叠处形成了跨越的聚类,破坏了数据集的结构。
为了解决无结构层次聚类中的问题,可以引入连接性约束,即在聚类过程中考虑数据点之间的连接性。这种方法可以更好地保持数据集的结构,形成更合理的聚类结果。以下是使用Python进行有结构层次聚类的代码示例:
from sklearn.neighbors import kneighbors_graph
# 定义k-最近邻连接性
connectivity = kneighbors_graph(X, n_neighbors=10, include_self=False)
# 执行有结构层次聚类
print("执行有结构层次聚类...")
st = time.time()
ward = AgglomerativeClustering(n_clusters=6, connectivity=connectivity, linkage="ward")
ward.fit(X)
elapsed_time = time.time() - st
label = ward.labels_
print(f"耗时:{elapsed_time:.2f}秒")
print(f"数据点数量:{label.size}")
# 绘制有结构层次聚类结果
fig2 = plt.figure()
ax2 = fig2.add_subplot(121, projection="3d", elev=7, azim=-80)
ax2.set_position([0, 0, 0.95, 1])
for l in np.unique(label):
ax2.scatter(X[label == l, 0], X[label == l, 1], X[label == l, 2],
color=plt.cm.jet(float(l) / np.max(label + 1)), s=20, edgecolor="k")
plt.suptitle(f"有连接性约束(耗时{elapsed_time:.2f}秒)")
plt.show()
在上述代码中,首先定义了k-最近邻连接性,然后在AgglomerativeClustering类中引入了连接性约束。最后,使用matplotlib库绘制了聚类结果。可以看到,有结构聚类在瑞士卷的不同折叠处形成了更合理的聚类结果,保持了数据集的结构。