从 sklearn 中的高斯混合模型中获取 PDF

Posted

技术标签:

【中文标题】从 sklearn 中的高斯混合模型中获取 PDF【英文标题】:Getting the PDF from the Gausian Mixture Model in sklearn 【发布时间】:2021-10-12 16:32:28 【问题描述】:

我已将高斯混合模型 (GMM) 拟合到我拥有的数据系列中。使用 GMM,我试图按元素获取另一个向量的概率。 Matlab 通过以下代码行实现了这一点。

a = reshape(0:1:15, 14, 1);
gm = fitgmdist(a, 13);  % 13 specifies the number of components (means and covs for example) in the fit model

% Testing with new data
b = reshape(-5:1:5, 11, 1);
pdf(gm, b) 

    0.0000
    0.0000
    0.0000
    0.0000
    0.0018
    0.0643
    0.0658
    0.0671
    0.0666
    0.0662
    0.0672

这是意料之中的,因为在拟合时提供的数据中不存在负值 -50,因此提供接近零的值。

我正在尝试使用带有sklearn 的python 来复制它。以下是我到目前为止所取得的成就。

from sklearn.mixture import GaussianMixture
import numpy as np

gm = GaussianMixture(n_components=13).fit(np.arange(16).reshape(-1, 1))

# Generate test data
b = np.arange(-5, 6)[:, None]
prob = gm.predict_proba(b).tolist()

"""
prob=
[[8.539939840944505e-152, 0.0, 1.9638856033086253e-68, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], 
[2.238593143299414e-141, 0.0, 3.166463050557315e-63, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], 
[5.868073258732079e-131, 0.0, 5.106947259415683e-58, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], 
[1.5382109014584666e-120, 0.0, 8.239047963148164e-53, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], 
[4.0321459413005606e-110, 0.0, 1.3296012030592655e-47, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], 
[8.790691487706948e-139, 0.0, 1.7850932827696813e-81, 8.316994953954272e-40, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], 
[6.040819196361928e-118, 0.0, 7.556403579572576e-66, 2.180313173877784e-29, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], 
[7.616317001277741e-99, 0.0, 5.870491452246584e-52, 1.0486913731065672e-20, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0], 
[1.761856615767359e-81, 0.9999999999999076, 8.370258307836422e-40, 9.254498458447064e-14, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], 
[7.477776611058069e-66, 0.0, 2.190323924113167e-29, 1.4984230843298664e-08, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.9999999850157694, 0.0, 0.0], 
[5.823053603579932e-52, 0.0, 1.0519204995101235e-20, 4.4513567127132954e-05, 0.0, 0.0, 0.9999554864328727, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]
"""

数组prob 返回一个矩阵,其中每一行表示属于n_components 数量类之一的概率(意味着沿行的总和 = 1)。然而,这不是预期的结果。我想知道b 的每个元素是从适合的gm 模型生成的概率,就像Matlab 一样。

如何通过 Python 实现这一点?谢谢。

【问题讨论】:

认为(可能是错误的)您对数字 13 在这里所做的事情的理解,无论是在 matlab 代码中还是在 sklearns 代码中都有一点缺陷。浏览完文档后,您在此处使用的数字 13 实质上是在传达模型,以便在您提供给模型的 16 个一维数据样本中找到 13 个不同的高斯分布。 这不是OP描述的吗?我的意思是,我不明白您的理解与 OP 的不同。 @sai,这是真的。在这两种语言中安装 GMM 时我没有任何问题。例如,两种语言的均值是13x1 向量。我的问题与下一步有关。我想要一个在 Python 中来自 Matlab 提供的 fit gm 模型的元素 PDF。我希望这次我的意图很明确。 我现在明白了。谢谢你的解释。 【参考方案1】:

predict_proba 查找将单个数据行分配给 GMM 所基于的每个组件(在您的情况下为 13 个组件)的概率。有关更多信息,请参阅 Jake VanderPlas 的excellent chapter。

要获取 pdf,您需要使用 score_samples 函数 - 该函数返回从拟合的 GMM 中提取每行的加权对数概率:

b = np.arange(-5, 6)[:, None]
log_probs = gm.score_samples(b)
sum_of_scores = (np.exp(log_probs)).sum()
probs = np.exp(log_probs) / sum_of_scores
print('Probs sum: ', probs.sum()) # confirm sums to 1
print('pdf: ', probs.tolist())

请注意,在这个玩具示例中,由于 K-Means 聚类在 GMM 拟合算法的初始部分的不确定性,您很可能不会从 matlab 重现确切结果,但如果您确实有一个更真实、多样化、采样良好的数据集来与 MATLAB 实现进行交叉检查,他们会更好地达成一致。

【讨论】:

所以您建议使用softmax 对其进行规范化? 是的,softmax,因为它是一个对数似然

以上是关于从 sklearn 中的高斯混合模型中获取 PDF的主要内容,如果未能解决你的问题,请参考以下文章

如何获得贝叶斯高斯混合模型的平滑连续 pdf?

使用高斯混合模型和 scikit learn 进行多类分类

使用分数度量评估高斯混合模型?

高斯混合模型交叉验证

高斯混合模型(GMM)

高斯混合模型 - 参数的 Matlab 训练