Python scikit-learn 1.3 聚类实战:3种算法对比与欧洲语言数据集应用

📅 2026/7/8 5:33:43
Python scikit-learn 1.3 聚类实战:3种算法对比与欧洲语言数据集应用
Python scikit-learn 1.3 聚类实战3种算法对比与欧洲语言数据集应用聚类分析是机器学习中无监督学习的重要分支它能帮助我们发现数据中隐藏的自然分组。本文将带你用Python的scikit-learn 1.3版本实战三种主流聚类算法系统聚类、K-Means和AgglomerativeClustering并应用于一个有趣的欧洲语言数据集。1. 环境准备与数据加载在开始之前确保你已经安装了以下Python库pip install scikit-learn1.3.0 pandas matplotlib seaborn numpy我们将使用一个特殊的欧洲语言距离矩阵作为示例数据。这个数据集记录了6种欧洲语言英语、挪威语、德语、法语、西班牙语、意大利语之间的距离这个距离是基于数字1-10的拼写差异计算的。import numpy as np import pandas as pd from scipy.spatial.distance import squareform # 语言缩写E(英语), N(挪威语), G(德语), Fr(法语), S(西班牙语), I(意大利语) languages [E, N, G, Fr, S, I] # 距离矩阵下三角 dist_matrix np.array([ [0], # E [2, 0], # N [6, 6, 0], # G [6, 6, 2, 0], # Fr [6, 6, 6, 6, 0], # S [6, 6, 6, 6, 2, 0] # I ]) # 转换为完整的对称距离矩阵 full_dist_matrix squareform(dist_matrix)2. 三种聚类算法原理与实现2.1 系统聚类Hierarchical Clustering系统聚类通过连续合并或分裂簇来构建树状图dendrogram。scikit-learn中的AgglomerativeClustering实现了这种方法。核心参数解析参数说明常用值n_clusters最终簇的数量整数linkage链接策略ward, complete, average, singleaffinity距离度量euclidean, manhattan, cosine, precomputedfrom sklearn.cluster import AgglomerativeClustering import matplotlib.pyplot as plt from scipy.cluster.hierarchy import dendrogram # 系统聚类实现 def plot_dendrogram(model, **kwargs): counts np.zeros(model.children_.shape[0]) n_samples len(model.labels_) for i, merge in enumerate(model.children_): current_count 0 for child_idx in merge: if child_idx n_samples: current_count 1 else: current_count counts[child_idx - n_samples] counts[i] current_count linkage_matrix np.column_stack([model.children_, model.distances_, counts]).astype(float) dendrogram(linkage_matrix, **kwargs) model AgglomerativeClustering(distance_threshold0, n_clustersNone, affinityprecomputed, linkagecomplete) model model.fit(full_dist_matrix) plt.figure(figsize(10, 6)) plt.title(欧洲语言谱系聚类图) plot_dendrogram(model, labelslanguages, orientationright) plt.show()2.2 K-Means聚类K-Means是最著名的动态聚类算法虽然通常用于欧式空间数据但我们可以通过多维缩放(MDS)将距离矩阵转换为适合K-Means的形式。from sklearn.manifold import MDS from sklearn.cluster import KMeans # 将距离矩阵转换为2维坐标 mds MDS(n_components2, dissimilarityprecomputed, random_state42) coordinates mds.fit_transform(full_dist_matrix) # K-Means聚类 kmeans KMeans(n_clusters3, random_state42) kmeans_labels kmeans.fit_predict(coordinates) # 可视化 plt.figure(figsize(8, 6)) plt.scatter(coordinates[:, 0], coordinates[:, 1], ckmeans_labels, cmapviridis) for i, lang in enumerate(languages): plt.annotate(lang, (coordinates[i, 0], coordinates[i, 1])) plt.title(K-Means聚类结果) plt.show()2.3 有序约束聚类AgglomerativeClustering模拟虽然scikit-learn没有直接实现有序聚类但我们可以通过调整AgglomerativeClustering的参数来模拟类似效果。# 使用AgglomerativeClustering模拟有序约束 ordered_model AgglomerativeClustering(n_clusters3, affinityprecomputed, linkagesingle) ordered_labels ordered_model.fit_predict(full_dist_matrix) # 结果展示 result_df pd.DataFrame({ Language: languages, SystemCluster: model.labels_, KMeans: kmeans_labels, OrderedLike: ordered_labels }) print(result_df)3. 算法对比与结果分析让我们从几个关键维度比较这三种算法1. 计算复杂度对比算法时间复杂度空间复杂度适合数据规模系统聚类O(n³)O(n²)中小型(n10000)K-MeansO(nki)O(nk)大型有序约束O(n²)O(n²)中小型2. 我们的语言数据集结果from sklearn.metrics import silhouette_score # 计算轮廓系数仅适用于K-Means和有序约束 kmeans_score silhouette_score(coordinates, kmeans_labels) ordered_score silhouette_score(coordinates, ordered_labels) print(fK-Means轮廓系数: {kmeans_score:.3f}) print(f有序约束轮廓系数: {ordered_score:.3f})3. 实际应用建议当数据有明确的距离/相似性定义时系统聚类是首选对于大型数据集K-Means更高效当数据有潜在的顺序关系时可尝试单链接(single linkage)的层次聚类4. 高级技巧与优化4.1 最佳簇数确定对于K-Means我们可以使用肘部法则和轮廓分析from sklearn.metrics import silhouette_samples # 肘部法则 inertia [] for k in range(2, 6): kmeans KMeans(n_clustersk, random_state42) kmeans.fit(coordinates) inertia.append(kmeans.inertia_) plt.figure(figsize(8, 4)) plt.plot(range(2, 6), inertia, bo-) plt.xlabel(簇数) plt.ylabel(SSE) plt.title(肘部法则) plt.show()4.2 距离度量选择当使用层次聚类时链接策略的选择至关重要完全链接(complete): 适合发现紧凑的、大小相近的簇单链接(single): 能发现非凸形状的簇但对噪声敏感平均链接(average): 平衡了上述两种方法的优缺点4.3 特征工程技巧对于距离矩阵数据可以考虑多维缩放(MDS) - 如我们前面所用t-SNE - 更适合可视化等距映射(Isomap) - 保留全局几何结构from sklearn.manifold import TSNE tsne TSNE(n_components2, metricprecomputed, random_state42) tsne_coords tsne.fit_transform(full_dist_matrix) plt.figure(figsize(8, 6)) plt.scatter(tsne_coords[:, 0], tsne_coords[:, 1], ckmeans_labels, cmapviridis) for i, lang in enumerate(languages): plt.annotate(lang, (tsne_coords[i, 0], tsne_coords[i, 1])) plt.title(t-SNE可视化) plt.show()在实际项目中我发现t-SNE虽然能产生漂亮的可视化效果但随机性较强不适合直接用于聚类。而MDS虽然计算成本较高但结果更稳定可靠。