在本节课程中,我们将探讨高斯混合模型(GMM)如何对新数据进行聚类。即:当我们输入一条新的数据时,模型会基于先前学习到的各个高斯分布的参数来估计该数据属于每个类别的概率。接下来,我们将详细了解这一过程的具体步骤。
1. 原理
当我们使用 GMM 进行数据聚类时,本质是估计新样本最有可能产自哪个高斯分布。
- 首先,根据高斯分布的权重、重要性对新数据给出粗略的可能性估计(先验概率)
- 然后,结合样本的高斯分布概率密度函数值,估计下输入样本最有可能出自哪个分布
- 最后,得出新样本属于不同高斯分布的后验概率,将新样本归属到概率最大的高斯分布
接下来,我们通过一个例子来理解 GMM 用来聚类的过程。下面公式为一元高斯分布的概率密度函数:
假设:GMM 经过对观测数据的拟合,得到关键的参数如下:
- 分布1: 均值 μ1 = 2,标准差 σ1 = 1, 权重 w1 = 0.6
- 分布2:均值 μ2 = 5,标准差 σ2 = 1.5,权重 w2 = 0.4
输入数据为 x = 4,我们需要计算它属于哪个分布的概率。首先,根据拟合结果,可知:
- 分布 1 先验概率:0.6
- 分布 2 先验概率:0.4
接下来,计算每个分布的概率密度函数值:
- 分布 1 概率密度 :\( f(4|1) ≈ 0.0539910 \)
- 分布 2 概率密度:\( f(4|2) ≈ 0.2129653 \)
最后,计算后验概率:
- 总概率:\( 0.6 * 0.0539910 + 0.4 * 0.2129653 = 0.11758072 \)
- 分布 1 后验概率:\( 0.6 * 0.0539910 / 0.11758072 = 0.23326053 \)
- 分布 2 后验概率:\( 0.4 * 0.2129653 / 0.11758072 = 0.76673947 \)
由计算结果可知,x = 4 由分布2产生的可能性更大,应该将其归属到这一类别。
import numpy as np from scipy.stats import norm def test(): params = [{'mean': 2, 'covariance': 1}, {'mean': 5, 'covariance': 1.5}] data = 4 pdfs = [] weight = [0.6, 0.5] for idx, param in enumerate(params): # 计算某点的概率密度值 pdf_value = norm.pdf(data, loc=param['mean'], scale=param['covariance']) pdfs.append(pdf_value) print('分布 %d 概率密度函数值: %.7f' % (idx + 1, pdf_value)) weighted_pdfs = np.array(pdfs) * np.array(weight) print('属于各个分布的概率:', weighted_pdfs / np.sum(weighted_pdfs)) if __name__ == '__main__': test()
2. 延伸
上一个例子中,我们使用的数据是一维的,对应到一元高斯分布。实际应用时,我们的数据大都是多维数据,同理,对应的是多元高斯分布。对于多元高斯分布,其概率密度函数计算公式如下:
假设 GMM(2个分布) 经过对训练数据的拟合,得到模型参数如下:
- 对于第一个高斯成分:
- 均值 \( μ1 = [1, 1] \)(在二维空间中,这个高斯分布的中心位置在 (1, 1) 点)。
- 协方差矩阵 \( \begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix} \)(表示在 x 和 y 方向上的方差都是 1,且两个维度不相关)。
- 混合系数 \( w1 = 0.6 \)(这个高斯成分占整个混合模型的比例是 0.6)。
- 对于第二个高斯成分:
- 均值 \( μ2 = [4, 4] \)(在二维空间中,这个高斯分布的中心位置在 (4, 4) 点)。
- 协方差矩阵 \( \begin{bmatrix} 0.5 & 0 \\ 0 & 0.5 \end{bmatrix} \)(表示在 x 和 y 方向上的方差都是 0.5,且两个维度不相关)。
- 混合系数 \( w2 = 0.4 \)(这个高斯成分占整个混合模型的比例是 0.4)。
假设有一个新样本 \( x = [2, 2] \)。首先,计算其先验概率:
- 分布 1 先验概率:\( 0.6 \)
- 分布 2 先验概率:\( 0.4 \)
接下来,计算每个分布的概率密度函数值:
- 分布 1 概率密度:\( f(4|1) ≈ 0.0585498\)
- 分布 2 概率密度:\( f(4|2) ≈ 0.0001068\)
最后,计算后验概率:
- 总概率:\( 0.6 * 0.0585498 + 0.4 * 0.0001068 = 0.0351726 \)
- 分布 1 后验概率:\( 0.6 * 0.0585 / 0.03514 = 0.9984825 \)
- 分布 2 后验概率:\( 0.4 * 0.0001 / 0.03514 = 0.0015175 \)
由计算结果可知,x = [2, 2] 由分布1产生的可能性更大,即:属于分布1的可性能更大。
import numpy as np from scipy.stats import multivariate_normal def test(): params = [{'mean': [1, 1], 'covariance': [[1, 0], [0, 1]]}, {'mean': [4, 4], 'covariance': [[0.5, 0], [0, 0.5]]}] data = [2, 2] pdfs = [] weight = [0.6, 0.5] for idx, param in enumerate(params): # 创建多元高斯分布对象 gaussian = multivariate_normal(mean=param['mean'], cov=param['covariance']) # 计算某点的概率密度值 pdf_value = gaussian.pdf(data) pdfs.append(pdf_value) print('分布 %d 概率密度函数值: %.7f' % (idx + 1, pdf_value)) weighted_pdfs = np.array(pdfs) * np.array(weight) print('属于各个分布的概率:', weighted_pdfs / np.sum(weighted_pdfs)) if __name__ == '__main__': test()