em算法系列1:python實現三硬幣模型
阿新 • • 發佈:2018-12-13
三硬幣模型
假設有3枚硬幣,分別記做A,B,C。這些硬幣正面出現的概率分別是π,p和q。進行如下擲硬幣實驗:先擲硬幣A,根據其結果選出硬幣B或C,正面選B,反面選硬幣C;然後投擲選重中的硬幣,出現正面記作1,反面記作0;獨立地重複n次(n=10),結果為1111110000 我們只能觀察投擲硬幣的結果,而不知其過程,估計這三個引數π,p和q。
EM演算法
可以看到投擲硬幣時到底選擇了B或者C是未知的。我們設隱藏變數Z 來指示來自於哪個硬幣,,令,觀察資料。
寫出生成一個硬幣時的概率: 有了一個硬幣的概率,我們就可以寫出所有觀察資料的log似然函式: 然後求似然函式最大值 其中。因為裡面帶著加和所以這個極大似然是求不出解析解的。 如果我們知道隱藏變數Z的話,求以下的似然會容易很多: L(θ|X,Z)=logP(X,Z|θ) 但是隱藏變數Z的值誰也不知道,所以我們轉用EM演算法求它的後驗概率期望的最大值。
- E步::假設當前模型的引數為時,隱含變數來自於硬幣B的後驗概率 那麼隱含變數來自於硬幣C的後驗概率自然為。
def cal_u(pi1,p1,q1,xi):
return pi1*math.pow(p1,xi) * math.pow(1-p1,1-xi)/\
float(pi1* math.pow(p1,xi) * math.pow(1-p1,1-xi)+
(1-pi1) * math.pow(q1,xi) * math.pow(1-q1,1-xi))
- M步: 先寫出似然關於後驗概率的期望,它是似然期望下界函式的最大值, 要注意這裡把看做固定值。然後我們分別求偏導,獲得引數的新估計值
def cal_u(pi, p, q, xi):
"""
u值計算
:param pi: 下一次迭代開始的 pi
:param p: 下一次迭代開始的 p
:param q: 下一次迭代開始的 q
:param xi: 觀察資料第i個值,從0開始
:return:
"""
return pi * math.pow(p, xi) * math.pow(1 - p, 1 - xi) / \
float(pi * math.pow(p, xi) * math.pow(1 - p, 1 - xi) +
(1 - pi) * math.pow(q, xi) * math.pow(1 - q, 1 - xi))
def e_step(pi,p,q,x):
"""
e步計算
:param pi: 下一次迭代開始的 pi
:param p: 下一次迭代開始的 p
:param q: 下一次迭代開始的 q
:param x: 觀察資料
:return:
"""
return [cal_u(pi,p,q,xi) for xi in x]
演算法首先選取引數初始值,然後迭代到收斂為止
python實現
# -*- coding: utf-8 -*-
import math
def cal_u(pi, p, q