
高斯混合模型实战从鸢尾花数据到K值选择1. 高斯混合模型的核心思想高斯混合模型Gaussian Mixture Model, GMM是一种基于概率分布的聚类方法它假设数据是由多个高斯分布组合生成的。与K-means等硬聚类方法不同GMM属于软聚类能够给出样本属于各个簇的概率。为什么选择GMM而非其他聚类方法灵活性通过调整协方差矩阵GMM可以识别不同形状球形、椭圆形的簇概率输出不仅给出聚类结果还提供样本属于各簇的概率密度估计能够估计整个数据空间的概率密度分布在Scikit-learn 1.4中GMM的实现进行了多项优化内存效率提升计算速度加快新增了收敛检测机制2. 环境准备与数据加载首先确保安装了正确版本的Scikit-learnpip install scikit-learn1.4.0加载必要的库和鸢尾花数据集import numpy as np import matplotlib.pyplot as plt from sklearn import datasets from sklearn.mixture import GaussianMixture from sklearn.metrics import silhouette_score import pandas as pd # 加载鸢尾花数据集 iris datasets.load_iris() X iris.data # 使用所有四个特征 y iris.target feature_names iris.feature_names提示虽然鸢尾花数据集有真实标签但在聚类任务中我们通常不使用这些标签仅用于最终评估聚类效果。3. 模型训练与可视化3.1 基础模型训练我们先训练一个简单的GMM模型假设已知类别数为3# 初始化GMM模型 gmm GaussianMixture(n_components3, random_state42) # 训练模型 gmm.fit(X) # 获取聚类结果 labels gmm.predict(X) probs gmm.predict_proba(X) # 获取属于各簇的概率3.2 二维可视化为了直观展示聚类效果我们选择两个特征进行可视化# 选择两个特征进行可视化花瓣长度和宽度 X_2d X[:, [2, 3]] # 重新训练模型 gmm_2d GaussianMixture(n_components3, random_state42) gmm_2d.fit(X_2d) labels_2d gmm_2d.predict(X_2d) # 可视化 plt.figure(figsize(10, 6)) plt.scatter(X_2d[:, 0], X_2d[:, 1], clabels_2d, s50, cmapviridis) # 绘制高斯分布的均值和椭圆 for i in range(3): # 提取均值和协方差 mean gmm_2d.means_[i] cov gmm_2d.covariances_[i] # 绘制椭圆 v, w np.linalg.eigh(cov) angle np.degrees(np.arctan2(w[0][1], w[0][0])) v 2. * np.sqrt(2.) * np.sqrt(v) ell plt.matplotlib.patches.Ellipse(mean, v[0], v[1], angle, colorred, alpha0.3) plt.gca().add_patch(ell) # 标记中心点 plt.scatter(mean[0], mean[1], markerx, s100, colorred) plt.xlabel(feature_names[2]) plt.ylabel(feature_names[3]) plt.title(GMM聚类结果二维投影) plt.colorbar(labelCluster) plt.show()4. 选择最优K值AIC与BIC在实际应用中我们往往不知道真实的簇数量。GMM提供了两种信息准则帮助选择K值AIC (Akaike Information Criterion)倾向于选择更复杂的模型BIC (Bayesian Information Criterion)对模型复杂度惩罚更大# 测试不同K值的AIC和BIC n_components_range range(1, 8) aics [] bics [] for n_components in n_components_range: gmm GaussianMixture(n_componentsn_components, random_state42) gmm.fit(X) aics.append(gmm.aic(X)) bics.append(gmm.bic(X)) # 可视化结果 plt.figure(figsize(10, 6)) plt.plot(n_components_range, aics, labelAIC) plt.plot(n_components_range, bics, labelBIC) plt.xlabel(Number of Components (K)) plt.ylabel(Information Criterion) plt.legend() plt.title(AIC和BIC随K值变化曲线) plt.xticks(n_components_range) plt.show()如何解读AIC/BIC曲线K值选择策略适用场景特点AIC最小值数据质量高噪声少倾向于选择更复杂的模型BIC最小值样本量较大对模型复杂度惩罚更强肘部法则直观判断选择曲线拐点处的K值5. 模型评估与结果分析5.1 聚类效果评估虽然聚类是无监督学习但我们仍有一些评估方法# 轮廓系数越高越好 silhouette_avg silhouette_score(X, labels) print(f轮廓系数: {silhouette_avg:.3f}) # 与真实标签比较仅在有标签时使用 from sklearn.metrics import adjusted_rand_score ari adjusted_rand_score(y, labels) print(f调整兰德指数: {ari:.3f})5.2 参数分析训练好的GMM模型包含以下关键参数# 输出模型参数 print(各簇权重:, gmm.weights_) print(\n均值向量:) for i, mean in enumerate(gmm.means_): print(f簇{i}: {np.round(mean, 2)}) print(\n协方差矩阵:) for i, cov in enumerate(gmm.covariances_): print(f簇{i}的协方差矩阵:) print(np.round(cov, 2))5.3 概率输出解析GMM的一个独特优势是提供样本属于各簇的概率# 获取概率最高的前5个样本 prob_df pd.DataFrame(probs, columns[fCluster_{i} for i in range(3)]) prob_df[Max_Cluster] prob_df.idxmax(axis1) print(prob_df.head())6. 高级应用与技巧6.1 协方差矩阵类型选择Scikit-learn提供了四种协方差矩阵类型类型参数适用场景全协方差full各簇有任意方向的椭圆形状对角协方差diag各特征独立椭圆轴平行坐标轴球形协方差spherical所有簇是圆形大小相同绑定协方差tied所有簇共享同一协方差矩阵# 比较不同协方差类型的效果 cov_types [full, diag, spherical, tied] for cov_type in cov_types: gmm GaussianMixture(n_components3, covariance_typecov_type, random_state42) gmm.fit(X) labels gmm.predict(X) score silhouette_score(X, labels) print(f{cov_type}协方差矩阵的轮廓系数: {score:.3f})6.2 处理高维数据当特征维度较高时可以考虑特征选择选择与聚类目标相关的特征降维使用PCA等降维方法正则化在协方差矩阵中添加小的常数防止奇异# PCA降维后聚类 from sklearn.decomposition import PCA pca PCA(n_components2) X_pca pca.fit_transform(X) gmm_pca GaussianMixture(n_components3, random_state42) gmm_pca.fit(X_pca) labels_pca gmm_pca.predict(X_pca) # 可视化 plt.figure(figsize(10, 6)) plt.scatter(X_pca[:, 0], X_pca[:, 1], clabels_pca, cmapviridis) plt.xlabel(Principal Component 1) plt.ylabel(Principal Component 2) plt.title(PCA降维后的GMM聚类) plt.show()7. 实际应用中的注意事项数据预处理标准化GMM对特征的尺度敏感异常值处理高斯分布对异常值敏感初始化策略K-means初始化默认随机初始化多次运行取最优收敛判断设置合理的max_iter和tol参数监控对数似然的变化# 带预处理和多次初始化的完整流程 from sklearn.preprocessing import StandardScaler from sklearn.pipeline import Pipeline # 创建管道 pipeline Pipeline([ (scaler, StandardScaler()), (gmm, GaussianMixture(n_components3, n_init5, # 多次初始化 max_iter500, tol1e-4, random_state42)) ]) pipeline.fit(X) final_labels pipeline.named_steps[gmm].predict(X)在实际项目中我发现GMM对初始化比较敏感特别是在高维空间中。一个实用的技巧是先用K-means进行粗聚类然后用其结果初始化GMMfrom sklearn.cluster import KMeans # 使用K-means初始化 kmeans KMeans(n_clusters3, random_state42) initial_means kmeans.fit(X).cluster_centers_ gmm_smart GaussianMixture(n_components3, means_initinitial_means, random_state42) gmm_smart.fit(X)