Scikit-learn 1.4.2 GMM 实战:3步完成鸢尾花数据集聚类与概率可视化
📅 2026/7/13 13:39:45
👁️ 阅读次数
📝 编程学习
Scikit-learn 1.4.2 GMM 实战:3步完成鸢尾花数据集聚类与概率可视化
鸢尾花数据集是机器学习领域的经典案例,但如何用概率视角解读其分类特性?本文将用Scikit-learn 1.4.2最新版本的高斯混合模型(GMM),带您实现从数据加载到三维概率可视化的完整流程。不同于传统硬聚类方法,GMM能给出每个数据点属于各类别的概率分布,这对理解数据重叠区域特别有价值。
1. 环境准备与数据理解
在开始建模前,我们需要配置合适的工具链并深入理解数据特性。现代Python数据科学栈为我们提供了高效的工具组合:
# 核心工具库 import numpy as np import pandas as pd import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D # Scikit-learn组件 from sklearn.datasets import load_iris from sklearn.mixture import GaussianMixture from sklearn.preprocessing import StandardScaler # 可视化扩展 import seaborn as sns plt.style.use('seaborn-v0_8-whitegrid')鸢尾花数据集包含150个样本,每个样本有4个特征(萼片长度、萼片宽度、花瓣长度、花瓣宽度)和对应的品种标签。我们先进行探索性分析:
iris = load_iris() X = iris.data y = iris.target features = iris.feature_names target_names = iris.target_names print(f"特征矩阵形状: {X.shape}") print(f"特征名称: {features}") print(f"目标类别: {target_names}")通过pairplot可以直观看到各类别的分布情况:
df = pd.DataFrame(X, columns=features) df['species'] = [target_names[i] for i in y] sns.pairplot(df, hue='species', palette='husl', height=2.5) plt.show()关键观察:
- 花瓣长度和宽度呈现明显的类别可分性
- 萼片特征存在较多重叠区域
- setosa与其他两类线性可分
- versicolor和virginica在部分特征空间有重叠
2. GMM模型构建与训练
Scikit-learn的GaussianMixture类提供了完整的GMM实现。我们需要重点关注三个核心参数:
n_components:混合高斯成分数量covariance_type:协方差矩阵类型init_params:初始化策略
2.1 数据预处理
虽然GMM对数据尺度不敏感,但标准化能提升EM算法的收敛速度:
scaler = StandardScaler() X_scaled = scaler.fit_transform(X) # 保留标准化参数用于后续逆变换 mean_vec = scaler.mean_ scale_vec = scaler.scale_2.2 模型训练与组件选择
通过BIC(贝叶斯信息准则)确定最优成分数:
n_components_range = range(1, 8) bic_values = [] for n in n_components_range: gmm = GaussianMixture(n_components=n, covariance_type='full', random_state=42) gmm.fit(X_scaled) bic_values.append(gmm.bic(X_scaled)) plt.plot(n_components_range, bic_values, 'bo-') plt.xlabel('Number of Components') plt.ylabel('BIC Score') plt.title('BIC for GMM') plt.show()BIC曲线解读:
- 当n_components=3时BIC达到最低点
- 验证了数据中确实存在三个自然类别
- 更多成分会导致过拟合
2.3 最终模型训练
best_n = 3 final_gmm = GaussianMixture(n_components=best_n, covariance_type='full', random_state=42) final_gmm.fit(X_scaled) # 获取训练结果 cluster_probs = final_gmm.predict_proba(X_scaled) cluster_labels = final_gmm.predict(X_scaled)模型参数解析:
weights_: 各高斯成分的混合权重means_: 各高斯成分的均值向量covariances_: 各高斯成分的协方差矩阵
3. 结果可视化与分析
3.1 二维特征空间投影
选择信息量最大的两个特征进行可视化:
plt.figure(figsize=(12, 6)) # 真实类别分布 plt.subplot(121) sns.scatterplot(x=X[:, 2], y=X[:, 3], hue=y, palette='viridis') plt.title('True Species Distribution') plt.xlabel('Petal Length') plt.ylabel('Petal Width') # GMM聚类结果 plt.subplot(122) sns.scatterplot(x=X[:, 2], y=X[:, 3], hue=cluster_labels, palette='viridis') plt.title('GMM Cluster Assignment') plt.xlabel('Petal Length') plt.ylabel('Petal Width') plt.tight_layout() plt.show()对比分析:
- GMM正确分离了setosa类别
- versicolor和virginica的边界区域存在少量误分类
- 概率模型能更好处理重叠区域
3.2 三维概率分布可视化
创建三维空间展示各点的最大类别概率:
# 准备三维绘图数据 x = X[:, 2] # 花瓣长度 y = X[:, 3] # 花瓣宽度 z = np.max(cluster_probs, axis=1) # 最大概率值 fig = plt.figure(figsize=(10, 8)) ax = fig.add_subplot(111, projection='3d') # 按真实类别着色 colors = ['r', 'g', 'b'] for i in range(best_n): mask = (y == i) ax.scatter(x[mask], y[mask], z[mask], c=colors[i], label=target_names[i], s=40, alpha=0.7) ax.set_xlabel('Petal Length') ax.set_ylabel('Petal Width') ax.set_zlabel('Cluster Probability') ax.set_title('3D Probability Distribution by True Species') ax.legend() plt.show()关键发现:
- 类别中心区域概率接近1.0
- 边界区域概率值在0.5-0.8之间
- setosa类别的概率分布最集中
- virginica在边缘有概率下降趋势
3.3 决策边界与概率等高线
# 创建网格数据 petal_length = np.linspace(X[:,2].min()-0.5, X[:,2].max()+0.5, 100) petal_width = np.linspace(X[:,3].min()-0.5, X[:,3].max()+0.5, 100) xx, yy = np.meshgrid(petal_length, petal_width) grid_data = np.column_stack([xx.ravel(), yy.ravel()]) # 标准化网格数据(仅使用花瓣特征) grid_scaled = (grid_data - mean_vec[2:]) / scale_vec[2:] full_grid = np.zeros((len(grid_scaled), 4)) full_grid[:, 2:] = grid_scaled # 预测网格点概率 Z = final_gmm.predict_proba(full_grid)[:, 0] # setosa概率 Z = Z.reshape(xx.shape) # 绘制等高线 plt.figure(figsize=(10, 8)) contour = plt.contourf(xx, yy, Z, levels=20, cmap='RdYlBu') plt.colorbar(contour, label='Setosa Probability') # 叠加原始数据点 sns.scatterplot(x=X[:, 2], y=X[:, 3], hue=y, palette='viridis', edgecolor='k', s=80) plt.title('Probability Contour for Setosa Class') plt.xlabel('Petal Length') plt.ylabel('Petal Width') plt.show()工程实践建议:
- 对于高维数据,建议先进行PCA降维再应用GMM
- 初始化使用k-means++通常比随机初始化收敛更快
- 监控收敛过程可通过设置
verbose=2参数 - 大数据集可考虑使用
max_iter和tol参数控制训练时间
# 高级配置示例 gmm_optimized = GaussianMixture( n_components=3, covariance_type='full', init_params='kmeans++', max_iter=500, tol=1e-4, verbose=2, random_state=42 )
编程学习
技术分享
实战经验