高斯混合模型初始化使用组件参数 - sklearn

6
我想使用sklearn.mixture.GaussianMixture存储高斯混合模型,以便稍后使用score_samples方法在样本点上生成样本或值。以下是一个示例,其中组件具有以下权重、均值和协方差。
import numpy as np
weights = np.array([0.6322941277066596, 0.3677058722933399])
mu = np.array([[0.9148052872961359, 1.9792961751316835], 
               [-1.0917396392992502, -0.9304220945910037]])
sigma = np.array([[[2.267889129267119, 0.6553245618368836], 
                        [0.6553245618368835, 0.6571014653342457]], 
                       [[0.9516607767206848, -0.7445831474157608], 
                        [-0.7445831474157608, 1.006599716443763]]])

然后我按以下方式初始化了混合物。
from sklearn import mixture
gmix = mixture.GaussianMixture(n_components=2, covariance_type='full')
gmix.weights_ = weights   # mixture weights (n_components,) 
gmix.means_ = mu          # mixture means (n_components, 2) 
gmix.covariances_ = sigma  # mixture cov (n_components, 2, 2) 

最后,我尝试根据参数生成样本,但出现了错误:
x = gmix.sample(1000)
NotFittedError: This GaussianMixture instance is not fitted yet. Call 'fit' with appropriate arguments before using this method.

我理解GaussianMixture旨在使用高斯混合拟合样本,但是否有一种方法可以提供最终值并从那里继续?


首先,您需要将数据输入模型进行训练,然后它才能生成随机样本。请参阅[sample()函数的文档](http://scikit-learn.org/stable/modules/generated/sklearn.mixture.GaussianMixture.html#sklearn.mixture.GaussianMixture.sample)。 - Vivek Kumar
我没有初始数据,我只有每个组件的参数。我正在寻找一种解决方法或替代的Python库。 - hashmuke
4个回答

4
你很棒,J.P.Petersen!看到你的回答后,我比较了使用“fit”方法引入的变化。似乎最初的实例化并没有创建所有的“gmix”属性。具体来说,它缺少以下属性,
covariances_
means_
weights_
converged_
lower_bound_
n_iter_
precisions_
precisions_cholesky_

在给定输入被赋值时,前三个被介绍。在其余部分中,对于我的应用程序,我只需要的属性是precisions_cholesky_,它是逆协方差矩阵的cholesky分解。作为最低要求,我将其添加如下:

gmix.precisions_cholesky_ = np.linalg.cholesky(np.linalg.inv(sigma)).transpose((0, 2, 1))

3

似乎有一个检查来确保模型已经被训练。您可以通过在设置参数之前使用非常小的数据集对GMM进行训练来欺骗它。就像这样:

gmix = mixture.GaussianMixture(n_components=2, covariance_type='full')
gmix.fit(rand(10, 2))  # Now it thinks it is trained
gmix.weights_ = weights   # mixture weights (n_components,) 
gmix.means_ = mu          # mixture means (n_components, 2) 
gmix.covariances_ = sigma  # mixture cov (n_components, 2, 2)
x = gmix.sample(1000)  # Should work now

2
为了理解正在发生的事情,GaussianMixture 首先会检查是否已经拟合
self._check_is_fitted()

这会触发以下检查

def _check_is_fitted(self):
    check_is_fitted(self, ['weights_', 'means_', 'precisions_cholesky_'])

最后是最后一个函数调用

def check_is_fitted(estimator, attributes, msg=None, all_or_any=all):

这个只检查分类器是否已经具有属性。


简而言之,你只需要设置precisions_cholesky_属性就可以让它工作(无需进行fit)。

gmix.precisions_cholesky_ = 0

应该可以解决问题(没试过所以不敢保证 :P)

但是,如果你想要“安全玩耍”,并且希望在scikit-learn更新其约束条件时有一个一致的解决方案,@J.P.Petersen的解决方案可能是最好的选择。


是的,这解释了一些问题。我最初尝试分配 gmix.precisions_cholesky_ = None,这样我就能够生成样本。但是,如果您调用 score_samples,它将期望该值为一个与协方差类似维度的numpy数组,因此这种方法不起作用。 - hashmuke

0
作为对@hashmuke答案的轻微替代,您可以直接使用GaussianMixture内部使用的精度计算:
import numpy as np
from scipy.stats import invwishart as IW
from sklearn.mixture import GaussianMixture as GMM
from sklearn.mixture._gaussian_mixture import _compute_precision_cholesky

n_dims = 5
mu1 = np.random.randn(n_dims)
mu2 = np.random.randn(n_dims)
Sigma1 = IW.rvs(n_dims, 0.1 * np.eye(n_dims))
Sigma2 = IW.rvs(n_dims, 0.1 * np.eye(n_dims))
gmm = GMM(n_components=2)
gmm.weights_ = np.array([0.2, 0.8])
gmm.means_ = np.stack([mu1, mu2])
gmm.covariances_ = np.stack([Sigma1, Sigma2])
gmm.precisions_cholesky_ = _compute_precision_cholesky(gmm.covariances_, 'full')
X, y = gmm.sample(1000)

根据您的协方差类型,应相应地将full更改为_compute_precision_cholesky的输入(将是fulldiagtiedspherical之一)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接