銅陵高端網(wǎng)站建設(shè)百度直播平臺(tái)
高斯混合模型(Gaussian Mixture Model,簡(jiǎn)稱 GMM)是一種概率模型,用于表示具有多個(gè)子群體的數(shù)據(jù)集,其中每個(gè)子群體的數(shù)據(jù)分布可以用高斯分布(正態(tài)分布)來(lái)描述。GMM 是一種軟聚類方法,意味著它為每個(gè)數(shù)據(jù)點(diǎn)分配一個(gè)屬于每個(gè)聚類的概率分布,而不是硬聚類方法中的嚴(yán)格分類。
GMM 的組成
一個(gè) GMM 由以下幾個(gè)部分組成:
- 聚類數(shù)量(K):模型中高斯分布(聚類)的數(shù)量。
- 均值向量(μkμk?):每個(gè)高斯分布的均值向量,其中?kk?表示聚類索引。
- 協(xié)方差矩陣(ΣkΣk?):每個(gè)高斯分布的協(xié)方差矩陣,描述了數(shù)據(jù)在各個(gè)維度上的分布范圍和形狀。
- 混合系數(shù)(πkπk?):每個(gè)高斯分布的權(quán)重,表示數(shù)據(jù)屬于該聚類的概率,所有混合系數(shù)之和為1。
GMM 的數(shù)學(xué)表達(dá)
GMM 的概率密度函數(shù)(PDF)可以表示為:
GMM 的學(xué)習(xí)
GMM 的參數(shù)學(xué)習(xí)通常使用 EM 算法進(jìn)行,EM算法前面有將,是一個(gè)策略優(yōu)化算法
24/11/14 算法筆記 EM算法期望最大化算法-CSDN博客
我們來(lái)看一下簡(jiǎn)單的GMM源代碼
import numpy as np
from scipy.stats import multivariate_normalclass GaussianMixture:def __init__(self, n_components, covariance_type='full', n_iter=100, random_state=None):self.n_components = n_components # 聚類數(shù)量self.covariance_type = covariance_type # 協(xié)方差類型self.n_iter = n_iter # 迭代次數(shù)self.random_state = random_state # 隨機(jī)種子self.weights_ = None # 混合系數(shù)self.means_ = None # 均值self.covariances_ = None # 協(xié)方差def _initialize_parameters(self, X):"""隨機(jī)初始化均值、協(xié)方差和權(quán)重"""n_samples, n_features = X.shapeself.weights_ = np.ones(self.n_components) / self.n_components # 初始化權(quán)重random_indices = np.random.choice(n_samples, self.n_components, replace=False)self.means_ = X[random_indices] # 隨機(jī)選擇均值self.covariances_ = np.array([np.eye(n_features)] * self.n_components) # 初始化協(xié)方差為單位矩陣def _e_step(self, X):"""E步驟:計(jì)算每個(gè)數(shù)據(jù)點(diǎn)屬于每個(gè)高斯分布的責(zé)任"""n_samples = X.shape[0]responsibilities = np.zeros((n_samples, self.n_components))for k in range(self.n_components):rv = multivariate_normal(mean=self.means_[k], cov=self.covariances_[k])responsibilities[:, k] = self.weights_[k] * rv.pdf(X)# 歸一化責(zé)任responsibilities /= responsibilities.sum(axis=1, keepdims=True)return responsibilitiesdef _m_step(self, X, responsibilities):"""M步驟:更新均值、協(xié)方差和權(quán)重"""n_samples = X.shape[0]effective_n = responsibilities.sum(axis=0) # 每個(gè)聚類的有效樣本數(shù)量# 更新權(quán)重self.weights_ = effective_n / n_samples# 更新均值self.means_ = np.dot(responsibilities.T, X) / effective_n[:, np.newaxis]# 更新協(xié)方差for k in range(self.n_components):diff = X - self.means_[k]self.covariances_[k] = np.dot(responsibilities[:, k] * diff.T, diff) / effective_n[k]def fit(self, X):"""訓(xùn)練模型"""self._initialize_parameters(X) # 初始化參數(shù)for _ in range(self.n_iter): # 迭代更新responsibilities = self._e_step(X) # E步驟self._m_step(X, responsibilities) # M步驟def predict(self, X):"""預(yù)測(cè)數(shù)據(jù)點(diǎn)的聚類標(biāo)簽"""responsibilities = self._e_step(X) # 計(jì)算責(zé)任return np.argmax(responsibilities, axis=1) # 返回最大責(zé)任的聚類索引def sample(self, n_samples):"""從模型中生成新樣本"""samples = np.zeros((n_samples, self.means_.shape[1]))for i in range(n_samples):k = np.random.choice(self.n_components, p=self.weights_) # 根據(jù)權(quán)重選擇聚類samples[i] = np.random.multivariate_normal(self.means_[k], self.covariances_[k]) # 生成樣本return samples
接下來(lái)讓我們分析下每段代碼
1.初始化函數(shù)?__init__
def __init__(self, n_components, covariance_type='full', n_iter=100, random_state=None):self.n_components = n_components # 聚類數(shù)量self.covariance_type = covariance_type # 協(xié)方差類型self.n_iter = n_iter # 迭代次數(shù)self.random_state = random_state # 隨機(jī)種子self.weights_ = None # 混合系數(shù)self.means_ = None # 均值self.covariances_ = None # 協(xié)方差
這是類的構(gòu)造函數(shù),用于初始化GMM模型的參數(shù):
n_components
:模型中高斯分布(聚類)的數(shù)量。covariance_type
:協(xié)方差矩陣的類型,可以是'full'
、'diag'
或'spherical'
,分別表示全協(xié)方差、對(duì)角協(xié)方差和球面協(xié)方差。n_iter
:EM算法的最大迭代次數(shù)。random_state
:隨機(jī)數(shù)生成器的種子,用于結(jié)果的可重復(fù)性。weights_
、means_
和covariances_
:這些屬性將在模型訓(xùn)練后存儲(chǔ)模型參數(shù)。
2.參數(shù)初始化函數(shù)?_initialize_parameters
def _initialize_parameters(self, X):"""隨機(jī)初始化均值、協(xié)方差和權(quán)重"""n_samples, n_features = X.shapeself.weights_ = np.ones(self.n_components) / self.n_components # 初始化權(quán)重random_indices = np.random.choice(n_samples, self.n_components, replace=False)self.means_ = X[random_indices] # 隨機(jī)選擇均值self.covariances_ = np.array([np.eye(n_features)] * self.n_components) # 初始化協(xié)方差為單位矩陣
這個(gè)函數(shù)用于隨機(jī)初始化模型參數(shù):
self.weights_
:權(quán)重初始化為均等分布。self.means_
:均值初始化為數(shù)據(jù)集中隨機(jī)選擇的點(diǎn)。self.covariances_
:協(xié)方差矩陣初始化為單位矩陣,適用于全協(xié)方差情況。- 協(xié)方差可以告訴我們兩個(gè)變量是如何一起變化的。如果兩個(gè)變量的協(xié)方差是正的,那么它們傾向于朝相同的方向變化;如果協(xié)方差是負(fù)的,那么一個(gè)變量增加時(shí),另一個(gè)變量?jī)A向于減少。
3.E步驟函數(shù)?_e_step
def _e_step(self, X):"""E步驟:計(jì)算每個(gè)數(shù)據(jù)點(diǎn)屬于每個(gè)高斯分布的責(zé)任"""n_samples = X.shape[0]responsibilities = np.zeros((n_samples, self.n_components))for k in range(self.n_components):#函數(shù)用于生成符合多元正態(tài)分布的隨機(jī)樣本。rv = multivariate_normal(mean=self.means_[k], cov=self.covariances_[k])responsibilities[:, k] = self.weights_[k] * rv.pdf(X)# 歸一化責(zé)任responsibilities /= responsibilities.sum(axis=1, keepdims=True)return responsibilities
E步驟計(jì)算每個(gè)數(shù)據(jù)點(diǎn)屬于每個(gè)高斯分布的責(zé)任(后驗(yàn)概率):
- 使用
multivariate_normal.pdf
計(jì)算每個(gè)高斯分布的PDF值。 - 將每個(gè)高斯分布的PDF值乘以相應(yīng)的權(quán)重,得到未歸一化的責(zé)任。
- 通過(guò)將每個(gè)數(shù)據(jù)點(diǎn)的責(zé)任除以其總和來(lái)歸一化責(zé)任,確保每個(gè)數(shù)據(jù)點(diǎn)的責(zé)任之和為1。
PDF值通常指的是概率密度函數(shù)(Probability Density Function)的值。概率密度函數(shù)是連續(xù)概率分布的一個(gè)核心概念,它描述了隨機(jī)變量在給定區(qū)間內(nèi)取值的概率密度。對(duì)于連續(xù)隨機(jī)變量,其概率密度函數(shù)的圖形可以告訴我們隨機(jī)變量取某個(gè)特定值的可能性。
4.M步驟函數(shù)?_m_step
def _m_step(self, X, responsibilities):"""M步驟:更新均值、協(xié)方差和權(quán)重"""n_samples = X.shape[0]effective_n = responsibilities.sum(axis=0) # 每個(gè)聚類的有效樣本數(shù)量# 更新權(quán)重self.weights_ = effective_n / n_samples# 更新均值self.means_ = np.dot(responsibilities.T, X) / effective_n[:, np.newaxis]# 更新協(xié)方差for k in range(self.n_components):diff = X - self.means_[k]self.covariances_[k] = np.dot(responsibilities[:, k] * diff.T, diff) / effective_n[k]
M步驟根據(jù)E步驟計(jì)算的責(zé)任更新模型參數(shù):
self.weights_
:權(quán)重更新為每個(gè)聚類的有效樣本數(shù)量除以總樣本數(shù)量。self.means_
:均值更新為加權(quán)平均,權(quán)重是每個(gè)數(shù)據(jù)點(diǎn)對(duì)每個(gè)聚類的責(zé)任。self.covariances_
:協(xié)方差更新為加權(quán)的樣本偏差的外積,權(quán)重是每個(gè)數(shù)據(jù)點(diǎn)對(duì)每個(gè)聚類的責(zé)任。
5.訓(xùn)練函數(shù)?fit
def fit(self, X):"""訓(xùn)練模型"""self._initialize_parameters(X) # 初始化參數(shù)for _ in range(self.n_iter): # 迭代更新responsibilities = self._e_step(X) # E步驟self._m_step(X, responsibilities) # M步驟
- 首先調(diào)用
_initialize_parameters
函數(shù)初始化參數(shù)。 - 然后進(jìn)行指定次數(shù)的迭代,每次迭代都包括E步驟和M步驟。
6.預(yù)測(cè)函數(shù)?predict
def predict(self, X):"""預(yù)測(cè)數(shù)據(jù)點(diǎn)的聚類標(biāo)簽"""responsibilities = self._e_step(X) # 計(jì)算責(zé)任return np.argmax(responsibilities, axis=1) # 返回最大責(zé)任的聚類索引
- 首先調(diào)用
_e_step
函數(shù)計(jì)算新數(shù)據(jù)點(diǎn)對(duì)每個(gè)聚類的責(zé)任。 - 然后返回責(zé)任最大的聚類索引作為預(yù)測(cè)標(biāo)簽。
7.采樣函數(shù)?sample
def sample(self, n_samples):"""從模型中生成新樣本"""samples = np.zeros((n_samples, self.means_.shape[1]))for i in range(n_samples):k = np.random.choice(self.n_components, p=self.weights_) # 根據(jù)權(quán)重選擇聚類samples[i] = np.random.multivariate_normal(self.means_[k], self.covariances_[k]) # 生成樣本return samples
- 首先初始化一個(gè)空的樣本數(shù)組。
- 然后根據(jù)每個(gè)聚類的權(quán)重隨機(jī)選擇一個(gè)聚類。
- 從選定的聚類對(duì)應(yīng)的高斯分布中生成一個(gè)樣本。
- 重復(fù)上述過(guò)程,直到生成所需數(shù)量的樣本。