高斯混合聚类和k 均值算法(k-means)都属于原型聚类,但与k均值用原型向量来刻画聚类结构不同,高斯混合聚类采用概率模型来表达聚类原型。

一、混合模型(Mixture Model)

混合模型是一个可以用来表示在总体分布(distribution)中含有 K 个子分布的概率模型。换句话说,混合模型表示了观测数据在总体中的概率分布,它是一个由 K 个子分布组成的混合分布。混合模型不要求观测数据提供关于子分布的信息,来计算观测数据在总体分布中的概率。

二、高斯混合模型(Gaussian Mixture Model,GMM)
1. 单高斯模型
  • 当样本数据 X 是一维数据(Univariate)时,高斯分布(也叫正态分布)遵从下方概率密度函数(Probability Density Function):

python 混合高斯分布 混合高斯模型聚类分析_GMM

正态分布通常也记为 python 混合高斯分布 混合高斯模型聚类分析_聚类_02,其中 python 混合高斯分布 混合高斯模型聚类分析_GMM_03数据均值(期望)python 混合高斯分布 混合高斯模型聚类分析_聚类_04 为数据标准差(Standard deviation)。

  • 当样本数据 X 是多维数据(Multivariate)时,(多元)高斯分布遵从下方概率密度函数:

python 混合高斯分布 混合高斯模型聚类分析_python 混合高斯分布_05

其中, python 混合高斯分布 混合高斯模型聚类分析_GMM_03 为数据均值(期望), python 混合高斯分布 混合高斯模型聚类分析_数据_07 为协方差矩阵,D 为数据维度。注意这里的 T 是矩阵转置符号,多维数据 python 混合高斯分布 混合高斯模型聚类分析_聚类_08

2. 高斯混合模型

高斯混合模型可以看作是由 K 个单高斯模型组合而成的模型,每个 Gaussian 称为一个“Component”,这 K 个子模型是混合模型的隐变量(Hidden variable)。也就是说我们假设样本中的每个数据都由这 K 个子模型中的某一个生成。一般来说,一个混合模型可以使用任何概率分布,这里使用高斯混合模型是因为高斯分布具备很好的数学性质以及良好的计算性能。下面给出高斯混合模型的数学定义:

首先定义如下信息:

  • python 混合高斯分布 混合高斯模型聚类分析_python 混合高斯分布_09
  • k 是混合模型中子高斯模型的编号,K是所有子模型的数量, k = 1,2,…,K
  • python 混合高斯分布 混合高斯模型聚类分析_数据_10观测数据属于第 k 个子模型的概率,它其实是一个“混合系数”,和下面的python 混合高斯分布 混合高斯模型聚类分析_数据_11相比,python 混合高斯分布 混合高斯模型聚类分析_数据_10相当于说先从k个子分布中选则一个子分布的概率。 python 混合高斯分布 混合高斯模型聚类分析_GMM_13
  • python 混合高斯分布 混合高斯模型聚类分析_数据_11 表示第 j 个观测数据python 混合高斯分布 混合高斯模型聚类分析_python 混合高斯分布_09属于第 k 个子模型的概率
  • python 混合高斯分布 混合高斯模型聚类分析_高斯混合模型_16 是第 k 个子模型的高斯分布密度函数, python 混合高斯分布 混合高斯模型聚类分析_聚类_17

那么,高斯混合模型的概率分布为:

python 混合高斯分布 混合高斯模型聚类分析_高斯混合模型_18

对于这个高斯混合模型python 混合高斯分布 混合高斯模型聚类分析_高斯混合模型_19)而言,参数 python 混合高斯分布 混合高斯模型聚类分析_GMM_20 表示每个子模型的期望(均值向量)、python 混合高斯分布 混合高斯模型聚类分析_python 混合高斯分布_21表示协方差矩阵、python 混合高斯分布 混合高斯模型聚类分析_高斯混合模型_22

根据上面的式子,如果我们要从 GMM 的分布中随机地取一个点的话,实际上可以分为两步:

  • 首先随机地在这 K 个 Component 之中选一个,每个 Component 被选中的概率实际上就是它的系数 python 混合高斯分布 混合高斯模型聚类分析_数据_10
  • 选中了 Component 之后,再单独地考虑从这个 Component 的分布中选取一个点就可以了──这里已经回到了普通的 Gaussian 分布,转化为了已知的问题。

那么如何用 GMM 来做聚类呢?其实很简单,现在我们有了数据,假定它们是由 GMM 生成出来的,那么我们只要根据数据推出 GMM 的概率分布来就可以了,然后 GMM 的 K 个 Component 实际上就对应了 K 个 cluster 了。根据数据来推算概率密度通常被称作“密度估计(density estimation)” ,特别地,当我们在已知(或假定)了概率密度函数的形式,而要估计其中的参数的过程被称作“参数估计”

GMM与K-means比较

  • 相同点:都是可用于聚类的算法;都需要指定K值。
  • 不同点:GMM可以给出一个样本属于某类的概率是多少。
三、极大似然估计

上面只是给出了 GMM 的概率密度,但是它的参数还是未知的,那么如何该如何求概率密度的参数呢?

先来聊聊似然函数。现在假设我们有 N 个数据点,并假设它们服从某个分布(记作 p(x) ),要确定里面的一些参数的值。现在这里的分布就是高斯混合分布,我们就需要确定 python 混合高斯分布 混合高斯模型聚类分析_高斯混合模型_24python 混合高斯分布 混合高斯模型聚类分析_python 混合高斯分布_21 这些参数。 我们的想法是,找到这样一组参数,它所确定的概率分布生成这些给定的数据点的概率最大,而这个概率实际上就等于 python 混合高斯分布 混合高斯模型聚类分析_GMM_26 ,我们把这个乘积称作似然函数 (Likelihood Function)

通常单个点的概率都很小,许多很小的数字相乘起来在计算机里很容易造成浮点数下溢,因此我们通常会对其取对数,把乘积变成加和 python 混合高斯分布 混合高斯模型聚类分析_GMM_27,得到对数似然函数(log-likelihood function) 。接下来我们只要将这个函数最大化(通常的做法是求导并令导数等于零,然后解方程),亦即找到这样一组参数值,它让似然函数取得最大值,我们就认为这是最合适的参数,这样就完成了参数估计的过程。下面让我们来看一看 GMM 的对数似然函数的具体形式 :

python 混合高斯分布 混合高斯模型聚类分析_数据_28

由于在对数函数里面又有加和,我们没法直接用求导解方程的办法直接求得最大值。为了解决这个问题,我们要用到 EM 算法。

四、EM算法

EM算法全程是 Expectation Maximization,即期望最大化算法,专门用来迭代求解极大似然估计。我们就是要找到最佳的模型参数,使得期望最大,“期望最大化算法”名字由此而来。

EM算法每次迭代包含两个步骤:

  • E-step:求期望 python 混合高斯分布 混合高斯模型聚类分析_高斯混合模型_29
  • M-step:求极大,计算新一轮迭代的模型参数。

这里不具体介绍一般性的 EM 算法(通过 Jensen 不等式得出似然函数的下界 Lower bound,通过极大化下界做到极大化似然函数),只介绍怎么在高斯混合模型里应用从来推算出模型参数。通过 EM 迭代更新高斯混合模型参数的方法如下:

假设:我们有样本数据 python 混合高斯分布 混合高斯模型聚类分析_数据_30

1. 首先初始化参数
2. E-step:依据当前参数,计算每个数据 j 来自子模型 k 的可能性

首先定义python 混合高斯分布 混合高斯模型聚类分析_数据_31 表示估计数据由每个 Component 生成的概率(并不是每个 Component 被选中的概率 python 混合高斯分布 混合高斯模型聚类分析_高斯混合模型_32 ):对于给定的样本 python 混合高斯分布 混合高斯模型聚类分析_GMM_33 来说,python 混合高斯分布 混合高斯模型聚类分析_数据_34是生成这个样本python 混合高斯分布 混合高斯模型聚类分析_GMM_33的子高斯分布,那么python 混合高斯分布 混合高斯模型聚类分析_数据_34的先验概率分布(大p)python 混合高斯分布 混合高斯模型聚类分析_python 混合高斯分布_37 就是前面定义的python 混合高斯分布 混合高斯模型聚类分析_高斯混合模型_32表示属于第k个子分布的概率。根据贝叶斯定理,python 混合高斯分布 混合高斯模型聚类分析_数据_34的后验分布为:

python 混合高斯分布 混合高斯模型聚类分析_数据_40

也就是说,PM 表示给定样本数据python 混合高斯分布 混合高斯模型聚类分析_GMM_33的情况下,它是由第k个Component生成的后验概率。(小p)python 混合高斯分布 混合高斯模型聚类分析_聚类_42就是高斯混合概率分布。

此外如果要做聚类的话,设每个python 混合高斯分布 混合高斯模型聚类分析_GMM_33样本的簇标记为python 混合高斯分布 混合高斯模型聚类分析_python 混合高斯分布_44,则:

python 混合高斯分布 混合高斯模型聚类分析_高斯混合模型_45

3. M-step:计算新一轮迭代的模型参数,并更新

估计每个 Component 的参数:现在我们假设上一步中得到的 python 混合高斯分布 混合高斯模型聚类分析_聚类_46 就是正确的“数据 python 混合高斯分布 混合高斯模型聚类分析_GMM_33 由 Component k 生成的概率”,亦可以当做该 Component 在生成 python 混合高斯分布 混合高斯模型聚类分析_GMM_33 这个数据上所做的贡献。或者说,我们可以看作 python 混合高斯分布 混合高斯模型聚类分析_GMM_33 这个值其中有 python 混合高斯分布 混合高斯模型聚类分析_高斯混合模型_50 这部分是由 Component k 所生成的。集中考虑所有的数据点,现在实际上可以看作 Component 生成了 python 混合高斯分布 混合高斯模型聚类分析_高斯混合模型_51 这些点。由于每个 Component 都是一个标准的 Gaussian 分布,可以很容易求出最大似然所对应的参数(python 混合高斯分布 混合高斯模型聚类分析_聚类_52)的值(分别对似然函数求导,见下面的详细推导部分):

python 混合高斯分布 混合高斯模型聚类分析_数据_53

python 混合高斯分布 混合高斯模型聚类分析_聚类_54

python 混合高斯分布 混合高斯模型聚类分析_python 混合高斯分布_55

3.1 python 混合高斯分布 混合高斯模型聚类分析_GMM_20

首先,对于给定的样本集D,GMM的对数似然函数python 混合高斯分布 混合高斯模型聚类分析_数据_57为:
python 混合高斯分布 混合高斯模型聚类分析_高斯混合模型_58

具体看看如何求python 混合高斯分布 混合高斯模型聚类分析_GMM_20。首先,若参数{python 混合高斯分布 混合高斯模型聚类分析_聚类_60}能使上式最大化,则对python 混合高斯分布 混合高斯模型聚类分析_GMM_20求导可得:python 混合高斯分布 混合高斯模型聚类分析_GMM_62。则:

python 混合高斯分布 混合高斯模型聚类分析_python 混合高斯分布_63

注意:

  • 第三行等号右边,分子因为除python 混合高斯分布 混合高斯模型聚类分析_数据_64之外都不含python 混合高斯分布 混合高斯模型聚类分析_数据_64,所以原来的求和只剩一项。
  • 一个矩阵乘A以一个向量x,对向量求导等于矩阵的逆python 混合高斯分布 混合高斯模型聚类分析_GMM_66,也就是python 混合高斯分布 混合高斯模型聚类分析_数据_67

又因为 python 混合高斯分布 混合高斯模型聚类分析_数据_68,所以: python 混合高斯分布 混合高斯模型聚类分析_聚类_69,里面的式子乘法分配率一下,再移动一项到等号右边得:python 混合高斯分布 混合高斯模型聚类分析_数据_70,于是最终得到:

python 混合高斯分布 混合高斯模型聚类分析_数据_71

这个式子也可以理解为各混合成分的均值可以通过加权平均来计算,样本权重是每个样本属于该成分的后验概率python 混合高斯分布 混合高斯模型聚类分析_数据_72

3.2 python 混合高斯分布 混合高斯模型聚类分析_python 混合高斯分布_73

类似的,可以得到python 混合高斯分布 混合高斯模型聚类分析_聚类_54

3.3 python 混合高斯分布 混合高斯模型聚类分析_高斯混合模型_32

除了要最大化python 混合高斯分布 混合高斯模型聚类分析_数据_57之外,还需满足python 混合高斯分布 混合高斯模型聚类分析_python 混合高斯分布_77,考虑拉格朗日乘子法:python 混合高斯分布 混合高斯模型聚类分析_GMM_78,再对 python 混合高斯分布 混合高斯模型聚类分析_高斯混合模型_32

python 混合高斯分布 混合高斯模型聚类分析_高斯混合模型_80

等式两边同时乘以python 混合高斯分布 混合高斯模型聚类分析_高斯混合模型_32得:python 混合高斯分布 混合高斯模型聚类分析_python 混合高斯分布_82,然后对所有混合成分(子分布)求和得:python 混合高斯分布 混合高斯模型聚类分析_数据_83,于是得到python 混合高斯分布 混合高斯模型聚类分析_python 混合高斯分布_84。再代入前面的这个式子可得:

python 混合高斯分布 混合高斯模型聚类分析_高斯混合模型_85

这个式子也可以理解为每个高斯成分的混合系数由(所有)样本属于该成分的后验概率确定。

至此,我们就得到了高斯混合模型的三个参数。

这样我们可以根据上一步得到的python 混合高斯分布 混合高斯模型聚类分析_数据_31(E步),在这一步中更新模型的三个参数的值(M步。

4. 重复计算 E-step 和 M-step 直至收敛

若达到最大迭代次数,或者似然函数python 混合高斯分布 混合高斯模型聚类分析_数据_57增长很少甚至不再增长,则得到最终的高斯混合模型。否则重复2,3两步。得到模型之后可以根据高斯混合分布对簇进行划分,也就是根据python 混合高斯分布 混合高斯模型聚类分析_数据_88

需要注意的是,EM 算法具备收敛性,但并不保证找到全局最大值,有可能找到局部最大值。解决方法是初始化几次不同的参数进行迭代,取结果最好的那次

5. GMM 实践

首先是生成随机的4个簇。然后使用 sklearn 内置的 GaussianMixture 模块进行聚类。

Python 代码实现

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LogNorm
from sklearn import mixture

# X为样本特征,Y为样本簇类别, 共1000个样本,每个样本2个特征,共4个簇,簇中心在[-1,-1], [0,0],[1,1], [2,2], 簇方差分别为[0.4, 0.2, 0.2]
X, y = make_blobs(n_samples=1000, n_features=2, centers=[[-1,-1], [0,0], [1,1], [2,2]], cluster_std=[0.4, 0.2, 0.2, 0.2], 
                  random_state =9)
plt.scatter(X[:, 0], X[:, 1], marker='o')
print(X.shape)
plt.show()

# concatenate the two datasets into the final training set
X_train = X #np.vstack([shifted_gaussian, stretched_gaussian])

# fit a Gaussian Mixture Model with two components
clf = mixture.GaussianMixture(n_components=4, covariance_type='full')
clf.fit(X_train)

Z = -clf.predict(X)
score= metrics.calinski_harabaz_score(X, y_pred) 

plt.scatter(X_train[:, 0], X_train[:, 1],c=Z)
plt.text(.99, .01, ('score: %.2f' % (score)),
                 transform=plt.gca().transAxes, size=10,
                 horizontalalignment='right')

plt.title('Negative log-likelihood predicted by a GMM')
plt.axis('tight')
plt.show()

看一下效果:

python 混合高斯分布 混合高斯模型聚类分析_聚类_89


参考:

[0]. 高斯混合模型

[1]. 高斯混合模型(GMM)

[2]. 漫谈 Clustering (3): Gaussian Mixture Model

[3]. EM及高斯混合模型

[4]. 如何通俗理解EM算法

[5]. 《机器学习(周志华)》,第9.4.3节:高斯混合聚类


THE END.