【问题标题】:Understanding Gaussian Mixture Models了解高斯混合模型
【发布时间】:2023-03-24 07:15:01
【问题描述】:

我正在尝试了解 scikit-learn 高斯混合模型实现的结果。看看下面的例子:

#!/opt/local/bin/python
import numpy as np
import matplotlib.pyplot as plt
from sklearn.mixture import GaussianMixture

# Define simple gaussian
def gauss_function(x, amp, x0, sigma):
    return amp * np.exp(-(x - x0) ** 2. / (2. * sigma ** 2.))

# Generate sample from three gaussian distributions
samples = np.random.normal(-0.5, 0.2, 2000)
samples = np.append(samples, np.random.normal(-0.1, 0.07, 5000))
samples = np.append(samples, np.random.normal(0.2, 0.13, 10000))

# Fit GMM
gmm = GaussianMixture(n_components=3, covariance_type="full", tol=0.001)
gmm = gmm.fit(X=np.expand_dims(samples, 1))

# Evaluate GMM
gmm_x = np.linspace(-2, 1.5, 5000)
gmm_y = np.exp(gmm.score_samples(gmm_x.reshape(-1, 1)))

# Construct function manually as sum of gaussians
gmm_y_sum = np.full_like(gmm_x, fill_value=0, dtype=np.float32)
for m, c, w in zip(gmm.means_.ravel(), gmm.covariances_.ravel(), 
               gmm.weights_.ravel()):
    gmm_y_sum += gauss_function(x=gmm_x, amp=w, x0=m, sigma=np.sqrt(c))

# Normalize so that integral is 1    
gmm_y_sum /= np.trapz(gmm_y_sum, gmm_x)

# Make regular histogram
fig, ax = plt.subplots(nrows=1, ncols=1, figsize=[8, 5])
ax.hist(samples, bins=50, normed=True, alpha=0.5, color="#0070FF")
ax.plot(gmm_x, gmm_y, color="crimson", lw=4, label="GMM")
ax.plot(gmm_x, gmm_y_sum, color="black", lw=4, label="Gauss_sum")

# Annotate diagram
ax.set_ylabel("Probability density")
ax.set_xlabel("Arbitrary units")

# Draw legend
plt.legend()
plt.show()

在这里,我首先生成由高斯构造的样本分布,然后将高斯混合模型拟合到这些数据。接下来,我想计算一些给定输入的概率。方便的是,scikit 实现提供了 score_samples 方法来做到这一点。现在我试图理解这些结果。我一直认为,我可以从 GMM 拟合中获取高斯参数,并通过对它们求和然后将积分归一化为 1 来构造完全相同的分布。但是,正如您在图中看到的那样,样本来自score_samples 方法与原始数据(蓝色直方图)完美匹配(红线),而手动构建的分布(黑线)则不匹配。我想了解我的想法哪里出错了,为什么我不能通过对 GMM 拟合给出的高斯求和来自己构建分布!?!非常感谢您的任何意见!

【问题讨论】:

    标签: python scikit-learn


    【解决方案1】:

    以防万一将来有人想知道同样的事情:必须规范化各个组件,而不是总和:

    import numpy as np
    import matplotlib.pyplot as plt
    from sklearn.mixture import GaussianMixture
    
    # Define simple gaussian
    def gauss_function(x, amp, x0, sigma):
        return amp * np.exp(-(x - x0) ** 2. / (2. * sigma ** 2.))
    
    # Generate sample from three gaussian distributions
    samples = np.random.normal(-0.5, 0.2, 2000)
    samples = np.append(samples, np.random.normal(-0.1, 0.07, 5000))
    samples = np.append(samples, np.random.normal(0.2, 0.13, 10000))
    
    # Fit GMM
    gmm = GaussianMixture(n_components=3, covariance_type="full", tol=0.001)
    gmm = gmm.fit(X=np.expand_dims(samples, 1))
    
    # Evaluate GMM
    gmm_x = np.linspace(-2, 1.5, 5000)
    gmm_y = np.exp(gmm.score_samples(gmm_x.reshape(-1, 1)))
    
    # Construct function manually as sum of gaussians
    gmm_y_sum = np.full_like(gmm_x, fill_value=0, dtype=np.float32)
    for m, c, w in zip(gmm.means_.ravel(), gmm.covariances_.ravel(), gmm.weights_.ravel()):
        gauss = gauss_function(x=gmm_x, amp=1, x0=m, sigma=np.sqrt(c))
        gmm_y_sum += gauss / np.trapz(gauss, gmm_x) * w
    
    # Make regular histogram
    fig, ax = plt.subplots(nrows=1, ncols=1, figsize=[8, 5])
    ax.hist(samples, bins=50, normed=True, alpha=0.5, color="#0070FF")
    ax.plot(gmm_x, gmm_y, color="crimson", lw=4, label="GMM")
    ax.plot(gmm_x, gmm_y_sum, color="black", lw=4, label="Gauss_sum", linestyle="dashed")
    
    # Annotate diagram
    ax.set_ylabel("Probability density")
    ax.set_xlabel("Arbitrary units")
    
    # Make legend
    plt.legend()
    
    plt.show()
    

    【讨论】:

    • 感谢您发布答案
    • 这真的很简洁,谢谢。我在将数据传递到GaussianMixture.fit 时遇到了很多麻烦,因为我没有意识到形状需要是np.expand_dims(samples, 1).shape 而不是samples.shape
    • 现在你将如何计算一个新的测试样本 X 的概率(这样你就可以估计数据点是否有可能是新的)?据我了解,np.exp(gmm.score_samples(X)) 给出了 X 处的 PDF 值,而不是 X 的概率。
    猜你喜欢
    • 2021-09-30
    • 2014-11-19
    • 2014-01-09
    • 2012-05-08
    • 2013-06-11
    • 2017-02-26
    • 2014-08-02
    • 2018-07-19
    • 2020-05-29
    相关资源
    最近更新 更多