混合高斯模型
Gaussian Mixed Model 表示多個高斯分佈的線性組合,設有隨機變量,則混合高斯模型表示如下其中可以認爲是高斯分佈的權重,表示第個高斯分量。
EM(expectation maximization)期望極大算法
這篇寫得太好了在此保存
以GMM爲例,已知樣本來自GMM,我們需要通過觀測樣本對GMM的權重,各個高斯模型的均值和方差進行估計。此時思考HMM模型要解決的第一個問題:已知觀測值和多個HMM模型,哪個HMM模型最優有可能產生這個觀測? 解決這個問題只需要代入模型求解出現該觀測的概率,然後選擇概率最大的模型即可。
但是混合高斯模型不能直接使用前向算法解決,因爲模型並不是已知,我們需要確定模型的參數,且參數不是從已知的模型中進行選擇,而是對未知的參數進行擬合。
EM迭代過程:
假設給定一個GMM,根據該模型對當前的樣本劃分類別(即每個樣本屬於哪個高斯分佈)。
樣本劃分完畢,求個各高斯分佈產生該樣本的概率,並且表示整個採樣數據產生的概率,然後最大化採樣數據概率。從而優化GMM的參數
如圖,來自上述推薦博客
Python仿真
代碼來自網絡,侵刪
import math
import copy
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# 生成隨機數據,4個高斯模型
def generate_data(sigma, N, mu1, mu2, mu3, mu4, alpha):
global X # 可觀測數據集
X = np.zeros((N, 2)) # 初始化X,2行N列。2維數據,N個樣本
X = np.matrix(X)
global mu # 隨機初始化mu1,mu2,mu3,mu4
mu = np.random.random((4, 2))
mu = np.matrix(mu)
global excep # 期望第i個樣本屬於第j個模型的概率的期望
excep = np.zeros((N, 4))
global alpha_ # 初始化混合項係數
alpha_ = [0.25, 0.25, 0.25, 0.25]
for i in range(N):
if np.random.random(1) < 0.1: # 生成0-1之間隨機數
X[i, :] = np.random.multivariate_normal(mu1, sigma, 1) # 用第一個高斯模型生成2維數據
elif 0.1 <= np.random.random(1) < 0.3:
X[i, :] = np.random.multivariate_normal(mu2, sigma, 1) # 用第二個高斯模型生成2維數據
elif 0.3 <= np.random.random(1) < 0.6:
X[i, :] = np.random.multivariate_normal(mu3, sigma, 1) # 用第三個高斯模型生成2維數據
else:
X[i, :] = np.random.multivariate_normal(mu4, sigma, 1) # 用第四個高斯模型生成2維數據
print("可觀測數據:\n", X) # 輸出可觀測樣本
print("初始化的mu1,mu2,mu3,mu4:", mu) # 輸出初始化的mu
def e_step(sigma, k, N):
global X
global mu
global excep
global alpha_
for i in range(N):
denom = 0
for j in range(0, k):
denom += alpha_[j] * math.exp(-(X[i, :] - mu[j, :]) * sigma.I * np.transpose(X[i, :] - mu[j, :])) / np.sqrt(
np.linalg.det(sigma)) # 分母
for j in range(0, k):
numer = math.exp(-(X[i, :] - mu[j, :]) * sigma.I * np.transpose(X[i, :] - mu[j, :])) / np.sqrt(
np.linalg.det(sigma)) # 分子
excep[i, j] = alpha_[j] * numer / denom # 求期望
print("隱藏變量:\n", excep)
def m_step(k, N):
global excep
global X
global alpha_
for j in range(0, k):
denom = 0 # 分母
numer = 0 # 分子
for i in range(N):
numer += excep[i, j] * X[i, :]
denom += excep[i, j]
mu[j, :] = numer / denom # 求均值
alpha_[j] = denom / N # 求混合項係數
if __name__ == '__main__':
iter_num = 1000 # 迭代次數
N = 500 # 樣本數目
k = 4 # 高斯模型數
probility = np.zeros(N) # 混合高斯分佈
u1 = [5, 35]
u2 = [30, 40]
u3 = [20, 20]
u4 = [45, 15]
sigma = np.matrix([[30, 0], [0, 30]]) # 協方差矩陣
alpha = [0.1, 0.2, 0.3, 0.4] # 混合項係數
generate_data(sigma, N, u1, u2, u3, u4, alpha) # 生成數據
# 迭代計算
for i in range(iter_num):
err = 0 # 均值誤差
err_alpha = 0 # 混合項係數誤差
Old_mu = copy.deepcopy(mu)
Old_alpha = copy.deepcopy(alpha_)
e_step(sigma, k, N) # E步
m_step(k, N) # M步
print("迭代次數:", i + 1)
print("估計的均值:", mu)
print("估計的混合項係數:", alpha_)
for z in range(k):
err += (abs(Old_mu[z, 0] - mu[z, 0]) + abs(Old_mu[z, 1] - mu[z, 1])) # 計算誤差
err_alpha += abs(Old_alpha[z] - alpha_[z])
if (err <= 0.001) and (err_alpha < 0.001): # 達到精度退出迭代
print(err, err_alpha)
break
# 可視化結果
# 畫分類好的數據
plt.subplot(222)
plt.title('classified data through EM')
order = np.zeros(N)
color = ['b', 'r', 'k', 'y']
for i in range(N):
for j in range(k):
if excep[i, j] == max(excep[i, :]):
order[i] = j # 選出X[i,:]屬於第幾個高斯模型
probility[i] += alpha_[int(order[i])] * math.exp(
-(X[i, :] - mu[j, :]) * sigma.I * np.transpose(X[i, :] - mu[j, :])) / (
np.sqrt(np.linalg.det(sigma)) * 2 * np.pi) # 計算混合高斯分佈
plt.scatter(X[i, 0], X[i, 1], c=color[int(order[i])], s=25, alpha=0.4, marker='o') # 繪製分類後的散點圖
# 繪製三維圖像
ax = plt.subplot(223, projection='3d')
plt.title('3d view')
for i in range(N):
ax.scatter(X[i, 0], X[i, 1], probility[i], c=color[int(order[i])])
plt.show()