【机器学习】详解高斯混合模型

当我们谈论高斯混合模型(后面,简写为 GMM)时,了解 KMeans 算法的工作原理是必不可少的。因为 GMM 与 KMeans 非常相似,所以它更可能是 KMeans 的概率版本。 这种概率特征使 GMM 可以应用于 KMeans 无法解决的许多复杂问题。

总之,KMeans 有以下限制:

1.它假设类簇是球形的并且大小相同,这在大多数现实世界的场景中是无效的。

2.它是一种硬聚类方法。 这意味着每个数据点只分配给一个簇。

由于这些限制,我们在进行机器学习项目时应该了解 KMeans 的替代方案。 在本文中,我们将探索 KMeans 聚类的最佳替代方案之一,称为高斯混合模型。

通过这篇文章,我们将了解以下几点。

1.高斯混合模型 (GMM) 算法的工作原理——通俗易懂。

2.GMM 背后的数学。

3.从头开始使用 Python 实现 GMM。

1

高斯混合模型 (GMM) 算法的工作原理

正如我前面提到的,我们可以将 GMM 称之为概率版本的 KMeans,因为 KMeans 和 GMM 的初始化和训练过程是相同的。但是,KMeans 使用基于距离的方法,而 GMM 使用概率方法。GMM 中有一个主要假设:数据集由多个高斯分布生成,换句话说,是高斯分布的混合。

0e7b2295bb41d48391e9dda31737fc5c.png

上述分布通常称为多模型分布。 每个峰代表我们数据集中不同的高斯分布或聚类。 但问题是,

                我们如何估计这些分布?

在回答这个问题之前,让我们先创建一些高斯分布。请注意,我正在生成多元正态分布;它是单变量正态分布的更高维扩展。

让我们定义数据点的均值和协方差。使用均值和协方差,我们可以生成如下分布。

# Set the mean and covariance
mean1 = [0, 0]
mean2 = [2, 0]
cov1 = [[1, .7], [.7, 1]]
cov2 = [[.5, .4], [.4, .5]]


# Generate data from the mean and covariance
data1 = np.random.multivariate_normal(mean1, cov1, size=1000)
data2 = np.random.multivariate_normal(mean2, cov2, size=1000)

让我们绘制数据

plt.figure(figsize=(10,6))


plt.scatter(data1[:,0],data1[:,1])
plt.scatter(data2[:,0],data2[:,1])


sns.kdeplot(data1[:, 0], data1[:, 1], levels=20, linewidth=10, color='k', alpha=0.2)
sns.kdeplot(data2[:, 0], data2[:, 1], levels=20, linewidth=10, color='k', alpha=0.2)


plt.grid(False)
plt.show()

1f04b6968382b9cd7accf92294a15f35.png

正如您在这里看到的,我们使用均值和协方差矩阵生成了随机高斯分布。 如果反转这个过程怎么样? 这正是 GMM 正在做的事情。 但是如何实现呢?

因为,一开始,我们对于类簇以及相关的均值和协方差矩阵没有任何了解。

好吧,它是根据以下步骤发生的,

1.为给定的数据集确定聚类的数量(为此,我们可以使用领域知识或其他方法,例如 BIC/AIC)。假设我们有 1000 个数据点,我们将组数设置为 2。

2.初始化每个集群的均值、协方差和权重参数。(我们将在后面的部分中对此进行更多探讨)

3.使用期望最大化算法执行以下操作,

    • 期望步骤(E步):计算每个数据点属于每个分布的概率,然后使用参数的当前估计评估似然函数

    • 最大化步骤(M步骤):更新之前的均值、协方差和权重参数,以最大化E步骤中找到的期望似然函数

    • 重复这些步骤,直到模型收敛。

有了这些信息,就结束了对 GMM 算法的非数学解释。

2

GMM 背后的数学

GMM 的核心在于上一节中描述的期望最大化 (EM) 算法。让我们演示一下 EM 算法在 GMM 中的应用。

步骤01:初始化均值、协方差和权重参数

    1.mean (μ): 随机初始化。

    2.协方差 (Σ):随机初始化

    3.权重(混合系数)(π):每个类的分数是指特定数据点属于每个类的可能性。 一开始,这对所有类簇都是相同的。 假设我们用三个分量拟合 GMM。 在这种情况下,每个组件的权重参数可能设置为 1/3,从而导致概率分布为 (1/3, 1/3, 1/3)。

步骤02:期望步骤(E步骤)

对于每个数据点𝑥𝑖:

使用以下等式计算数据点属于簇 (𝑐) 的概率。k 分布的个数。

25c370b9c1972d372340dc8ae92bf95d.png

其中𝜋_𝑐是高斯分布c的混合系数(有时称为权重),它在前一阶段被初始化,𝑁(𝒙|𝝁,𝚺)描述了高斯分布的概率密度函数(PDF),均值为𝜇和 关于数据点 x 的协方差 Σ; 我们可以如下表示。

aeaf11a16e7e417819f391bf6bd57fdb.png

E-step 使用模型参数的当前估计值计算这些概率。这些概率通常称为高斯分布的“责任”。它们由变量 r_ic 表示,其中 i 是数据点的索引,c 是高斯分布的索引。责任衡量第 c 个高斯分布生成第 i 个数据点的可能性。这里使用条件概率,更具体地说,是贝叶斯定理。

让我们举一个简单的例子。假设我们有 100 个数据点,需要将它们聚类成两组。我们可以这样写 r_ic(i=20,c=1) 。其中 i 代表数据点的索引,c 代表我们正在考虑的簇的索引。

请注意,在开始时,𝜋_𝑐 初始化为每个簇 c = 1,2,3,..,k 相等。在我们的例子中,𝜋_1 = 𝜋_2 = 1/2。

097f9949cf582887d8ecd3ba669bfce7.png

E-step 的结果是数值集合,集合中每个值代表每个数据点和每个高斯分布的责任大小。这些责任在 M 步中用于更新模型参数的估计。

步骤03:最大化步骤(M步)

在此步骤中,算法使用高斯分布的责任(在 E 步中计算)来更新模型参数的估计值。

M-step按如下方式更新参数的估计:

e1d5a9df229d4c4fb3182c937584fe4f.png

1.使用上面的公式4 更新 πc(混合系数)。

2.使用上面公式 5 更新 μc。

3.然后使用公式6 更新 Σc。

这个更新的估计在下一个 E-step 中用于计算数据点的新的责任值。

依此类推,此过程将重复直到算法收敛,也就是模型参数从一次迭代到下一次迭代没有显着变化。

让我们将以上内容总结成一个简单的图表,

9feb9df075cef2dbe34d47babd120189.png

在编码方面不用担心; 每个方程式只需要一行代码就能实现。 让我们开始使用 Python 从头开始实现 GMM。

3

从头开始使用 Python 实现 GMM。

17b33426f033bf66f031b895cc602f7f.gif

首先,让我们创建一个假数据集。在本节中,我将为一维数据集实现 GMM。

import numpy as np


n_samples = 100
mu1, sigma1 = -5, 1.2 
mu2, sigma2 = 5, 1.8 
mu3, sigma3 = 0, 1.6 


x1 = np.random.normal(loc = mu1, scale = np.sqrt(sigma1), size = n_samples)
x2 = np.random.normal(loc = mu2, scale = np.sqrt(sigma2), size = n_samples)
x3 = np.random.normal(loc = mu3, scale = np.sqrt(sigma3), size = n_samples)


X = np.concatenate((x1,x2,x3))

让我们创建一个辅助函数来绘制我们的数据。

from scipy.stats import norm


def plot_pdf(mu,sigma,label,alpha=0.5,linestyle='k--',density=True):
    """
    Plot 1-D data and its PDF curve.


    """
    # Compute the mean and standard deviation of the data


    # Plot the data
    
    X = norm.rvs(mu, sigma, size=1000)
    
    plt.hist(X, bins=50, density=density, alpha=alpha,label=label)


    # Plot the PDF
    x = np.linspace(X.min(), X.max(), 1000)
    y = norm.pdf(x, mu, sigma)
    plt.plot(x, y, linestyle)

绘制生成的数据如下。 请注意,我没有绘制数据本身,而是绘制了每个样本的概率密度。

plot_pdf(mu1,sigma1,label=r"$\mu={} \ ; \ \sigma={}$".format(mu1,sigma1))
plot_pdf(mu2,sigma2,label=r"$\mu={} \ ; \ \sigma={}$".format(mu2,sigma2))
plot_pdf(mu3,sigma3,label=r"$\mu={} \ ; \ \sigma={}$".format(mu3,sigma3))
plt.legend()
plt.show()

401ffc13dff10ed0adcd652cb62c28f6.png

让我们构建上一节中描述的每个步骤,

步骤 01:初始化均值、协方差和权重

def random_init(n_compenents):
    
    """Initialize means, weights and variance randomly 
      and plot the initialization
    """
    
    pi = np.ones((n_compenents)) / n_compenents
    means = np.random.choice(X, n_compenents)
    variances = np.random.random_sample(size=n_compenents)


    plot_pdf(means[0],variances[0],'Random Init 01')
    plot_pdf(means[1],variances[1],'Random Init 02')
    plot_pdf(means[2],variances[2],'Random Init 03')
    
    plt.legend()
    plt.show()
    
    return means,variances,pi

步骤02:期望步骤(E步骤)

def step_expectation(X,n_components,means,variances):
    """E Step
    
    Parameters
    ----------
    X : array-like, shape (n_samples,)
        The data.
    n_components : int
        The number of clusters
    means : array-like, shape (n_components,)
        The means of each mixture component.
    variances : array-like, shape (n_components,)
        The variances of each mixture component.
        
    Returns
    -------
    weights : array-like, shape (n_components,n_samples)
    """
    weights = np.zeros((n_components,len(X)))
    for j in range(n_components):
        weights[j,:] = norm(loc=means[j],scale=np.sqrt(variances[j])).pdf(X)
    return weights

在这个函数之后,我们介绍了我们在 E 步骤中讨论的前两个方程。 在这里,我们为当前模型参数均值和方差生成了高斯分布。 我们通过使用 scipy 的 stat 模块实现了这一点。 之后,我们使用pdf方法计算属于每个簇的每个数据点的可能性。

步骤03:最大化步骤(M步)

def step_maximization(X,weights,means,variances,n_compenents,pi):
    """M Step
    
    Parameters
    ----------
    X : array-like, shape (n_samples,)
        The data.
    weights : array-like, shape (n_components,n_samples)
        initilized weights array
    means : array-like, shape (n_components,)
        The means of each mixture component.
    variances : array-like, shape (n_components,)
        The variances of each mixture component.
    n_components : int
        The number of clusters
    pi: array-like (n_components,)
        mixture component weights
        
    Returns
    -------
    means : array-like, shape (n_components,)
        The means of each mixture component.
    variances : array-like, shape (n_components,)
        The variances of each mixture component.
    """
    r = []
    for j in range(n_compenents):  


        r.append((weights[j] * pi[j]) / (np.sum([weights[i] * pi[i] for i in range(n_compenents)], axis=0)))


        #5th equation above
        means[j] = np.sum(r[j] * X) / (np.sum(r[j]))
        
        #6th equation above
        variances[j] = np.sum(r[j] * np.square(X - means[j])) / (np.sum(r[j]))
        
        #4th equation above
        pi[j] = np.mean(r[j])


    return variances,means,pi

让我们实现训练循环。

def train_gmm(data,n_compenents=3,n_steps=50, plot_intermediate_steps_flag=True):
    """ Training step of the GMM model
    
    Parameters
    ----------
    data : array-like, shape (n_samples,)
        The data.
    n_components : int
        The number of clusters
    n_steps: int
        number of iterations to run
    """
    
    #intilize model parameters at the start
    means,variances,pi = random_init(n_compenents)


    for step in range(n_steps):
        #perform E step
        weights = step_expectation(data,n_compenents,means,variances)
        #perform M step
        variances,means,pi = step_maximization(X, weights, means, variances, n_compenents, pi)


    plot_pdf(means,variances)

当我们开始模型训练时,我们会根据我们设置的n_steps参数做E步和M步。但在实际用例中,你会更频繁地使用 GMM 的 scikit-learn 版本。 在那里您可以找到其他参数,例如

tol:定义模型的停止标准。当下限平均增益低于 tol 参数时,EM 迭代将停止。
init_params:用于初始化权重的方法

好吧,让我们看看我们手工制作的 GMM 表现如何。

fcea545e821279bb97210c7dd8263e65.png

在上图中,红色虚线表示原始分布,而其他图表示学习到的分布。第 30 次迭代后,我们可以看到我们的模型在这个玩具数据集上表现良好。

总结

本文旨在对高斯混合模型进行全面的指导; 但是,我们鼓励读者尝试不同的机器学习算法,因为没有一种最佳算法可以很好地解决所有问题。 此外,我们选择的机器学习算法的复杂性也值得注意。 GMM 的一个常见问题是它不能很好地扩展到大型数据集。

 
 

7087c6926d9a84298a8771dbfa11ba4c.jpeg

 
 
 
 
 
 
 
 
往期精彩回顾




适合初学者入门人工智能的路线及资料下载(图文+视频)机器学习入门系列下载机器学习及深度学习笔记等资料打印《统计学习方法》的代码复现专辑机器学习交流qq群955171419,加入微信群请扫码
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值