龙空技术网

ML基础:高斯混合模型是什么?

CDA数据分析师 178

前言:

今天姐妹们对“高斯混合模型拟合”都比较珍视,我们都想要了解一些“高斯混合模型拟合”的相关内容。那么小编在网摘上网罗了一些有关“高斯混合模型拟合””的相关文章,希望看官们能喜欢,咱们一起来了解一下吧!

1.高斯混合模型概念

高斯混合模型是一种概率模型,它假设所有数据点都是从有限数量的高斯分布的混合参数中生成的。实际上,可以将混合模型视为对 k-means聚类算法的扩展,它包含了数据的协方差结构以及隐高斯模型中心的信息。该方法使用了高斯分布作为参数模型,并使用了期望最大(Expectation Maximization,简称EM)算法进行训练。

2.基本原理与相关知识

2.1 高斯分布

高斯分布(Gaussian distribution)经常被称为正态分布(normal distribution),是一种在自然界大量存在的、最为常见的分布形式。下图是一张标准的高斯分布曲线图,两头低,中间高,左右对称因其曲线呈钟形,因此人们又经常称之为钟形曲线:

高斯分布的概率密度函数公式如下:

公式中包含两个参数,参数μ表示均值,参数σ表示标准差,均值对应正态分布的中间位置,在本例中我们可以推测均值在180cm附近。标准差衡量了数据围绕均值分散的程度。

注意:在实践中,概率分布要先进行归一化,也就是说曲线下面的面积之和需要为1,这样才能确保返回的概率密度在允许的取值范围内。

2. 期望最大化算法(EM)与高斯模型训练

模型的EM训练过程:

观察采样的概率值和模型概率值的接近程度,来判断一个模型是否拟合良好。调整模型以让新模型更适配采样的概率值。反复迭代这个过程很多次,直到两个概率值非常接近时,我们停止更新并完成模型训练。

模型生成的数据来决定似然值,即通过模型来计算数据的期望值。通过更新参数μ和σ来让期望值最大化。这个过程可以不断迭代直到两次迭代中生成的参数变化非常小为止。该过程和k-means的算法训练过程很相似(k-means不断更新类中心来让结果最大化),只不过在这里的高斯模型中,需要同时更新两个参数:分布的均值和标准差

3. 高斯混合模型实际案例

虽然GMM经常用于聚类,但我们可以将获得的聚类与数据集中的实际类别进行比较。我们用训练集中的类的均值初始化高斯矩阵的均值,以使这种比较有效。

使用iris数据集上的各种GMM协方差类型,在训练和测试数据上绘制预测标签。将gmm与球形、对角线、满协方差矩阵和绑定协方差矩阵按性能递增顺序进行比较。尽管人们期望完全协方差在一般情况下表现最好,但它容易在小数据集上过度拟合,并不能很好地推广到测试数据上。

如下图,训练集以点表示,验证集以叉表示。iris数据集是四维的。这里只显示了前两个维度,因此有些点在其他维度上是分离的。

# Author: Ron Weiss <ronweiss@gmail.com>, Gael Varoquaux# Modified by Thierry Guillemot <thierry.guillemot.work@gmail.com># License: BSD 3 clause​import matplotlib as mplimport matplotlib.pyplot as plt​import numpy as np​from sklearn import datasetsfrom sklearn.mixture import GaussianMixturefrom sklearn.model_selection import StratifiedKFold​print(__doc__)​colors = ['navy', 'turquoise', 'darkorange']​​def make_ellipses(gmm, ax):    for n, color in enumerate(colors):        if gmm.covariance_type == 'full':            covariances = gmm.covariances_[n][:2, :2]        elif gmm.covariance_type == 'tied':            covariances = gmm.covariances_[:2, :2]        elif gmm.covariance_type == 'diag':            covariances = np.diag(gmm.covariances_[n][:2])        elif gmm.covariance_type == 'spherical':            covariances = np.eye(gmm.means_.shape[1]) * gmm.covariances_[n]        v, w = np.linalg.eigh(covariances)        u = w[0] / np.linalg.norm(w[0])        angle = np.arctan2(u[1], u[0])        angle = 180 * angle / np.pi  # convert to degrees        v = 2. * np.sqrt(2.) * np.sqrt(v)        ell = mpl.patches.Ellipse(gmm.means_[n, :2], v[0], v[1],                                  180 + angle, color=color)        ell.set_clip_box(ax.bbox)        ell.set_alpha(0.5)        ax.add_artist(ell)        ax.set_aspect('equal', 'datalim')​iris = datasets.load_iris()​# Break up the dataset into non-overlapping training (75%) and testing# (25%) sets.skf = StratifiedKFold(n_splits=4)# Only take the first fold.train_index, test_index = next(iter(skf.split(iris.data, iris.target)))​​X_train = iris.data[train_index]y_train = iris.target[train_index]X_test = iris.data[test_index]y_test = iris.target[test_index]​n_classes = len(np.unique(y_train))​# Try GMMs using different types of covariances.estimators = {cov_type: GaussianMixture(n_components=n_classes,              covariance_type=cov_type, max_iter=20, random_state=0)              for cov_type in ['spherical', 'diag', 'tied', 'full']}​n_estimators = len(estimators)​plt.figure(figsize=(3 * n_estimators // 2, 6))plt.subplots_adjust(bottom=.01, top=0.95, hspace=.15, wspace=.05,                    left=.01, right=.99)​​for index, (name, estimator) in enumerate(estimators.items()):    # Since we have class labels for the training data, we can    # initialize the GMM parameters in a supervised manner.    estimator.means_init = np.array([X_train[y_train == i].mean(axis=0)                                    for i in range(n_classes)])​    # Train the other parameters using the EM algorithm.    estimator.fit(X_train)​    h = plt.subplot(2, n_estimators // 2, index + 1)    make_ellipses(estimator, h)​    for n, color in enumerate(colors):        data = iris.data[iris.target == n]        plt.scatter(data[:, 0], data[:, 1], s=0.8, color=color,                    label=iris.target_names[n])    # Plot the test data with crosses    for n, color in enumerate(colors):        data = X_test[y_test == n]        plt.scatter(data[:, 0], data[:, 1], marker='x', color=color)​    y_train_pred = estimator.predict(X_train)    train_accuracy = np.mean(y_train_pred.ravel() == y_train.ravel()) * 100    plt.text(0.05, 0.9, 'Train accuracy: %.1f' % train_accuracy,             transform=h.transAxes)​    y_test_pred = estimator.predict(X_test)    test_accuracy = np.mean(y_test_pred.ravel() == y_test.ravel()) * 100    plt.text(0.05, 0.8, 'Test accuracy: %.1f' % test_accuracy,             transform=h.transAxes)​    plt.xticks(())    plt.yticks(())    plt.title(name)​plt.legend(scatterpoints=1, loc='lower right', prop=dict(size=12))​plt.show()

4. k-means和GMM的关系

在特定条件下,k-means和GMM方法可以互相用对方的思想来表达。在k-means中根据距离每个点最接近的类中心来标记该点的类别,这里存在的假设是每个类簇的尺度接近且特征的分布不存在不均匀性。这也解释了为什么在使用k-means前对数据进行归一会有效果。高斯混合模型则不会受到这个约束,因为它对每个类簇分别考察特征的协方差模型。

K-means算法可以被视为高斯混合模型(GMM)的一种特殊形式。整体上看,高斯混合模型能提供更强的描述能力,因为聚类时数据点的从属关系不仅与近邻相关,还会依赖于类簇的形状。n维高斯分布的形状由每个类簇的协方差来决定。在协方差矩阵上添加特定的约束条件后,可能会通过GMM和k-means得到相同的结果。

实践中如果每个类簇的协方差矩阵绑定在一起(就是说它们完全相同),并且矩阵对角线上的协方差数值保持相同,其他数值则全部为0,这样能够生成具有相同尺寸且形状为圆形类簇。在此条件下,每个点都始终属于最近的中间点对应的类。

在k-means方法中使用EM来训练高斯混合模型时对初始值的设置非常敏感。而对比k-means,GMM方法有更多的初始条件要设置。实践中不仅初始类中心要指定,而且协方差矩阵和混合权重也要设置。可以运行k-means来生成类中心,并以此作为高斯混合模型的初始条件。由此可见并两个算法有相似的处理过程,主要区别在于模型的复杂度不同。

整体来看,所有无监督机器学习算法都遵循一条简单的模式:给定一系列数据,训练出一个能描述这些数据规律的模型(并期望潜在过程能生成数据)。训练过程通常要反复迭代,直到无法再优化参数获得更贴合数据的模型为止。

(1)获取更多优质内容及精彩资讯,可前往:

(2)了解更多数据领域的优质课程:

标签: #高斯混合模型拟合