簡體   English   中英

在Python中使用具有固定協方差的高斯混合

[英]Fit mixture of Gaussians with fixed covariance in Python

我有一些2D數據(GPS數據)與簇(停止位置),我知道它類似於具有特征標准偏差的高斯(與GPS樣本的固有噪聲成比例)。 下圖顯示了我期望有兩個這樣的聚類的樣本。 圖像寬25米,高13米。

在此輸入圖像描述

sklearn模塊有一個函數sklearn.mixture.GaussianMixture ,它允許您將高斯混合物擬合到數據中。 該函數有一個參數covariance_type ,使您可以假設有關高斯形狀的不同內容。 例如,您可以使用'tied'參數假設它們是統一的。

但是,似乎不能直接假設協方差矩陣保持不變。 sklearn源代碼中進行修改似乎是微不足道的,但是使用允許此更新的拉取請求感覺有點過分(我也不想在sklearn意外添加錯誤)。 是否有更好的方法將混合擬合到每個高斯的協方差矩陣固定的數據?

我想假設SD應該保持恆定在每個組件大約3米,因為這大致是我的GPS樣本的噪音水平。

我認為最好的選擇是通過定義一個新的scikit-learn類來“滾動你自己的” GMM模型,該類繼承自GaussianMixture並覆蓋方法以獲得你想要的行為。 這樣您就可以自己實現一個實現,而不必更改scikit-learn代碼(並創建一個pull-request)。

可能有用的另一個選擇是在scikit-learn中查看GMM貝葉斯版本 您可能能夠為協方差矩陣設置先驗,以便協方差是固定的。 它似乎使用Wishart分布作為協方差的先驗。 但是我對這個發行版不太熟悉,無法幫助你。

編寫自己的EM算法實現非常簡單。 它也會讓你對這個過程有一個很好的直覺。 我假設協方差是已知的,並且組件的先驗概率是相等的,並且僅適合於均值。

該類看起來像這樣(在Python 3中):

import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import multivariate_normal

class FixedCovMixture:
    """ The model to estimate gaussian mixture with fixed covariance matrix. """
    def __init__(self, n_components, cov, max_iter=100, random_state=None, tol=1e-10):
        self.n_components = n_components
        self.cov = cov
        self.random_state = random_state
        self.max_iter = max_iter
        self.tol=tol

    def fit(self, X):
        # initialize the process:
        np.random.seed(self.random_state)
        n_obs, n_features = X.shape
        self.mean_ = X[np.random.choice(n_obs, size=self.n_components)]
        # make EM loop until convergence
        i = 0
        for i in range(self.max_iter):
            new_centers = self.updated_centers(X)
            if np.sum(np.abs(new_centers-self.mean_)) < self.tol:
                break
            else:
                self.mean_ = new_centers
        self.n_iter_ = i

    def updated_centers(self, X):
        """ A single iteration """
        # E-step: estimate probability of each cluster given cluster centers
        cluster_posterior = self.predict_proba(X)
        # M-step: update cluster centers as weighted average of observations
        weights = (cluster_posterior.T / cluster_posterior.sum(axis=1)).T
        new_centers = np.dot(weights, X)
        return new_centers


    def predict_proba(self, X):
        likelihood = np.stack([multivariate_normal.pdf(X, mean=center, cov=self.cov) 
                               for center in self.mean_])
        cluster_posterior = (likelihood / likelihood.sum(axis=0))
        return cluster_posterior

    def predict(self, X):
        return np.argmax(self.predict_proba(X), axis=0)

在像您這樣的數據上,模型會快速收斂:

np.random.seed(1)
X = np.random.normal(size=(100,2), scale=3)
X[50:] += (10, 5)

model = FixedCovMixture(2, cov=[[3,0],[0,3]], random_state=1)
model.fit(X)
print(model.n_iter_, 'iterations')
print(model.mean_)

plt.scatter(X[:,0], X[:,1], s=10, c=model.predict(X))
plt.scatter(model.mean_[:,0], model.mean_[:,1], s=100, c='k')
plt.axis('equal')
plt.show();

和輸出

11 iterations
[[9.92301067 4.62282807]
 [0.09413883 0.03527411]]

您可以看到估計的中心( (9.9, 4.6)(0.09, 0.03) )接近真實的中心( (10, 5)(0, 0) )。

在此輸入圖像描述

首先,您可以使用spherical選項,它將為每個組件提供單個方差值。 通過這種方式,您可以檢查自己,如果收到的差異值太大,那么就會出現問題。

如果您想預設差異,則問題會退化為僅為您的組件找到最佳中心。 例如,您可以使用k-means來完成。 如果您不知道組件的數量,則可以掃描所有邏輯值(例如1到20)並評估擬合錯誤的減量。 或者,您可以優化自己的EM功能,同時查找中心和組件數量。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM