GMM混合高斯模型的EM演算法及Python實現

2021-08-10 14:41:04 字數 4492 閱讀 8008

1.演算法理論p(

x)=∑

kk=1

πkn(

x|μk

,εk)

n(x|μk

,εk)

=1(2

π)d|

εk|√

exp(

−12(

xi−μ

k)tε

−1k(

xi−μ

k))

∑kk=1πk

=1

用極大似然法處理問題:

輸入: (i = 1~n)

最小化: e(

πk,μ

k,εk

)=−∑

ni=1

log[

p(xi

)]=

−∑ni=1l

og(∑

kk=1

1(2π

)d|ε

k|√e

xp(−

12(x

i−μk

)tε−

1k(x

i−μk

)))

這是乙個非凸問題,只能求區域性極值,一般採用em演算法。

步驟如下:

1.隨機化πk

,μk,

εk2.e步:計算γn

,k=π

kn(x

n|μk

,εk)

∑kk=

1n(x

n|μk

,εk)

上式表示:第n個樣本落在第k個高斯的概率

3.m步: nk

=∑kk

=1γn

,k表示n個樣本中有多少屬於第k個高斯

開始更新: πn

ewk=

nkn

μnew

k=1n

k∑nn

=1γn

,kxn

εnewk=

1nk∑

nn=1

γn,k

(xn−

μnew

k)(x

n−μn

ewk)

t 4.回到2直至收斂

python實現

**基於

在此基礎上進行理解。

# 計算高斯函式

def gaussian(data,mean,cov):

dim = np.shape(cov)[0] # 計算維度

covdet = np.linalg

.det(cov) # 計算|cov|

covinv = np.linalg

.inv(cov) # 計算cov的逆

if covdet==0: # 以防行列式為0

covdet = np.linalg

.det(cov+np.eye(dim)*0.01)

covinv = np.linalg

.inv(cov+np.eye(dim)*0.01)

m = data - mean

z = -0.5 * np.dot(np.dot(m, covinv),m) # 計算exp()裡的值

return 1.0/(np.power(np.power(2*np.pi,dim)*abs(covdet),0.5))*np.exp(z) # 返回概率密度值

# 用於判斷初始聚類簇中的means是否距離離得比較近

defisdistance

(means,criterion=0.03):

k=len(means)

for i in range(k):

for j in range(i+1,k):

if criterion>np.linalg.norm(means[i]-means[j]):

return

false

return

true

# 獲取最初的聚類中心

defgetinitialmeans

(data,k,criterion):

dim = data.shape[1] # 資料的維度

means = [ for k in range(k)] # 儲存均值

minmax=

for i in range(dim):

minmax=np.array(minmax)

while

true:

for i in range(k):

means[i]=

for j in range(dim):

means[i]=np.array(means[i])

if isdistance(means,criterion):

break

return means

# k均值演算法,估計大約幾個樣本屬於乙個gmm

defkmeans

(data,k):

n = data.shape[0] # 樣本數量

dim = data.shape[1] # 樣本維度

means = getinitialmeans(data,k,15)

means_old = [np.zeros(dim) for k in range(k)]

# 收斂條件

while np.sum([np.linalg.norm(means_old[k] - means[k]) for k in range(k)]) > 0.01:

means_old = cp.deepcopy(means)

numlog = [0] * k # 儲存屬於某類的個數

sumlog = [np.zeros(dim) for k in range(k)]

# e步

for i in range(n):

dislog = [np.linalg.norm(data[i]-means[k]) for k in range(k)]

tok = dislog.index(np.min(dislog))

numlog[tok]+=1

# 屬於該類的樣本數量加1

sumlog[tok]+=data[i] # 儲存屬於該類的樣本取值

# m步

for k in range(k):

means[k]=1.0 / numlog[k] * sumlog[k]

return means

defgmm

(data,k):

n = data.shape[0]

dim = data.shape[1]

means= kmeans(data,k)

convs=[0]*k

# 初始方差等於整體data的方差

for i in range(k):

convs[i]=np.cov(data.t)

pis = [1.0/k] * k

gammas = [np.zeros(k) for i in range(n)]

loglikelyhood = 0

oldloglikelyhood = 1

while np.abs(loglikelyhood - oldloglikelyhood) > 0.0001:

oldloglikelyhood = loglikelyhood

# e步

for i in range(n):

res = [pis[k] * gaussian(data[i],means[k],convs[k]) for k in range(k)]

sumres = np.sum(res)

for k in range(k): # gamma表示第n個樣本屬於第k個混合高斯的概率

gammas[i][k] = res[k] / sumres

# m步

for k in range(k):

nk = np.sum([gammas[n][k] for n in range(n)]) # n[k] 表示n個樣本中有多少屬於第k個高斯

pis[k] = 1.0 * nk/n

means[k] = (1.0/nk)*np.sum([gammas[n][k] * data[n] for n in range(n)],axis=0)

xdiffs = data - means[k]

convs[k] = (1.0/ nk)*np.sum([gammas[n][k]* xdiffs[n].reshape(dim,1) * xdiffs[n] for n in range(n)],axis=0)

# 計算最大似然函式

loglikelyhood = np.sum(

[np.log(np.sum([pis[k] * gaussian(data[n], means[k], convs[k]) for k in range(k)])) for n in range(n)])

print (means)

print (loglikelyhood)

混合高斯模型(GMM)與EM演算法

有乙個資料集d d d 中的每個資料點是這樣產生的,先從k個類別中選擇乙個類別,然後從該類別對應的資料產生分布中產生資料點。若k選1的對應的分布是multinoulli分布,每個類別對應的資料產生分布是不同的高斯分布,估計資料點x對應的分布。這個問題對應的模型就是乙個混合高斯模型,具體的資料產生過程...

機器學習 高斯混合模型GMM和EM演算法

高斯混合模型就是用高斯 概率密度函式 正態分佈 曲線 精確地量化事物,它是乙個將事物分解為若干的基於高斯概率密度函式 正態分佈曲線 形成的模型。高斯混合模型 gmm 顧名思義,就是資料可以看作是從數個單高斯分布 gsm 中生成出來的。雖然我們可以用不同的分布來隨意地構造 xx mixture mod...

GMM高斯混合模型

在一般的分類問題中,通常的套路都是提取特徵,將特徵輸入分類器訓練,得到最終的模型。但是在具體操作時,一開始提出的特徵和輸入分類器訓練的特徵是不一樣的。比如假設有n張 100 100 100 100 的影象,分別提取它們的hog特徵x rp q x rp q,p p為特徵的維數,q q 為這幅影象中h...