Scikit-learn 1.4.2 GMM 实战:3步完成鸢尾花数据集聚类与概率可视化

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实现。我们需要重点关注三个核心参数:

  1. n_components:混合高斯成分数量
  2. covariance_type:协方差矩阵类型
  3. 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()

工程实践建议

  1. 对于高维数据,建议先进行PCA降维再应用GMM
  2. 初始化使用k-means++通常比随机初始化收敛更快
  3. 监控收敛过程可通过设置verbose=2参数
  4. 大数据集可考虑使用max_itertol参数控制训练时间
# 高级配置示例 gmm_optimized = GaussianMixture( n_components=3, covariance_type='full', init_params='kmeans++', max_iter=500, tol=1e-4, verbose=2, random_state=42 )