[英]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樣本的噪音水平。
編寫自己的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.