期望极大算法(Expectation Maximization Algorithm,EM)
定义
输入:观测变量数据Y,隐变量数据Z,联合分布P(Y,Z|
θ
\theta
θ),条件分布PP(Z,Y|
θ
\theta
θ);
输出:模型参数
θ
\theta
θ
(1)选择参数的初值
θ
(
0
)
,
开始迭代
;
\theta^{(0)},开始迭代;
θ(0),开始迭代;
(2)E步:记
θ
(
i
)
为第
i
次迭代参数
\theta^{(i)}为第i次迭代参数
θ(i)为第i次迭代参数
θ
\theta
θ的估计值,在第
i
+
1
i+1
i+1次迭代的E步,计算
Q ( θ , θ ( i ) ) = E Z [ l o g P ( Y , Z ∣ θ ) ∣ Y , θ ( i ) ] = ∑ Z l o g P ( Y , Z ∣ θ ) P ( Z ∣ Y , θ ( i ) ) Q(\theta,\theta^{(i)}) = E_Z\big[ log P(Y,Z|\theta)|Y,\theta^{(i)} \big] = \sum_{Z}log P(Y,Z|\theta) P(Z|Y,\theta^{(i)}) Q(θ,θ(i))=EZ[logP(Y,Z∣θ)∣Y,θ(i)]=Z∑logP(Y,Z∣θ)P(Z∣Y,θ(i))
P
(
Z
∣
Y
,
θ
(
i
)
)
P(Z|Y,\theta^{(i)})
P(Z∣Y,θ(i)):给定观测数据
Y
Y
Y和当前的参数估计
θ
(
i
)
\theta^{(i)}
θ(i)下隐变量数据
Z
Z
Z的条件概率分布;
(3)M步:求使
Q
(
θ
,
θ
(
i
)
)
Q(\theta,\theta^{(i)})
Q(θ,θ(i))极大化的
θ
\theta
θ,确定第
i
+
1
i+1
i+1次迭代的参数的估计值
θ
(
i
+
1
)
\theta^{(i+1)}
θ(i+1)
θ
(
i
+
1
)
=
a
r
g
∗
m
a
x
θ
Q
(
θ
,
θ
(
i
)
)
\theta^{(i+1)} = arg * \mathop{max}\limits_{\theta} Q(\theta,\theta^{(i)})
θ(i+1)=arg∗θmaxQ(θ,θ(i))
(4)重复第(2)步和第(3)步,直到收敛。
输入空间
T = { ( x 1 , x 2 , … , x N } T=\left\{(x_1,x_2,\dots,x_N\right\} T={(x1,x2,…,xN}
import numpy as np
import random
import math
import time
def loadData(mu0, sigma0, mu1, sigma1, alpha0, alpha1):
'''
初始化数据集
这里通过服从高斯分布的随机函数来生成数据集
:param mu0: 高斯0的均值
:param sigma0: 高斯0的方差
:param mu1: 高斯1的均值
:param sigma1: 高斯1的方差
:param alpha0: 高斯0的系数
:param alpha1: 高斯1的系数
:return: 混合了两个高斯分布的数据
'''
#定义数据集长度为1000
length = 1000
#初始化第一个高斯分布,生成数据,数据长度为length * alpha系数,以此来
#满足alpha的作用
data0 = np.random.normal(mu0, sigma0, int(length * alpha0))
#第二个高斯分布的数据
data1 = np.random.normal(mu1, sigma1, int(length * alpha1))
#初始化总数据集
#两个高斯分布的数据混合后会放在该数据集中返回
dataSet = []
#将第一个数据集的内容添加进去
dataSet.extend(data0)
#添加第二个数据集的数据
dataSet.extend(data1)
#对总的数据集进行打乱(其实不打乱也没事,只不过打乱一下直观上让人感觉已经混合了
# 读者可以将下面这句话屏蔽以后看看效果是否有差别)
random.shuffle(dataSet)
#返回伪造好的数据集
return dataSet
# mu0是均值μ
# sigmod是方差σ
#在设置上两个alpha的和必须为1,其他没有什么具体要求,符合高斯定义就可以
alpha0 = 0.3; mu0 = -2; sigmod0 = 0.5
alpha1 = 0.7; mu1 = 0.5; sigmod1 = 1
#初始化数据集
dataSetList = loadData(mu0, sigmod0, mu1, sigmod1, alpha0, alpha1)
np.shape(dataSetList)
print('alpha0:%.1f, mu0:%.1f, sigmod0:%.1f, alpha1:%.1f, mu1:%.1f, sigmod1:%.1f'%(
alpha0, mu0, sigmod0, alpha1, mu1, sigmod1
))
统计学习方法
模型
a r g ∗ m a x θ Q ( θ , θ ( i ) ) arg * \mathop{max}\limits_{\theta} Q(\theta,\theta^{(i)}) arg∗θmaxQ(θ,θ(i))
策略
L ( θ ) = l o g ( ∑ Z P ( Y ∣ Z , θ ) P ( Z ∣ θ ) ) L(\theta) = log\bigg( \sum_{Z} P(Y|Z,\theta) P(Z|\theta) \bigg) L(θ)=log(Z∑P(Y∣Z,θ)P(Z∣θ))
算法
高斯混合模型
P
(
y
∣
θ
)
=
∑
k
=
1
K
α
k
ϕ
(
y
∣
θ
k
)
,
α
k
:
系数
,
α
k
≥
0
,
∑
k
=
1
K
α
k
=
1
;
ϕ
(
y
∣
θ
k
)
:
高斯分布密度
,
θ
k
=
(
μ
k
,
σ
k
2
)
P(y|\theta) = \sum_{k=1}^K \alpha_k \phi(y|\theta_k),\alpha_k:系数,\alpha_k \geq 0,\sum_{k=1}^K \alpha_k = 1;\phi(y|\theta_k):高斯分布密度,\theta_k=(\mu_k,\sigma_k^2)
P(y∣θ)=k=1∑Kαkϕ(y∣θk),αk:系数,αk≥0,k=1∑Kαk=1;ϕ(y∣θk):高斯分布密度,θk=(μk,σk2)
ϕ
(
y
∣
θ
k
)
=
1
2
π
σ
k
e
x
p
(
−
(
y
−
μ
k
)
2
2
σ
k
2
)
\phi(y|\theta_k) = \frac{1}{\sqrt{2\pi}\sigma_k} exp \bigg( - \frac{(y-\mu_k)^2}{2\sigma_k^2} \bigg)
ϕ(y∣θk)=2πσk1exp(−2σk2(y−μk)2)
def calcGauss(dataSetArr, mu, sigmod):
'''
根据高斯密度函数计算值
:param dataSetArr: 可观测数据集
:param mu: 均值
:param sigmod: 方差
:return: 整个可观测数据集的高斯分布密度(向量形式)
'''
result = (1 / (math.sqrt(2 * math.pi) * sigmod)) * \
np.exp(-1 * (dataSetArr - mu) * (dataSetArr - mu) / (2 * sigmod**2))
#返回结果
return result
Q
(
θ
,
θ
(
i
)
)
=
E
Z
[
l
o
g
P
(
Y
,
Z
∣
θ
)
∣
Y
,
θ
(
i
)
]
=
∑
Z
l
o
g
P
(
Y
,
Z
∣
θ
)
P
(
Z
∣
Y
,
θ
(
i
)
)
Q(\theta,\theta^{(i)}) = E_Z\big[ log P(Y,Z|\theta)|Y,\theta^{(i)} \big] = \sum_{Z}log P(Y,Z|\theta) P(Z|Y,\theta^{(i)})
Q(θ,θ(i))=EZ[logP(Y,Z∣θ)∣Y,θ(i)]=Z∑logP(Y,Z∣θ)P(Z∣Y,θ(i))
P
(
Z
∣
Y
,
θ
(
i
)
)
:
给定观测数据
Y
和当前的参数估计
θ
(
i
)
下隐变量数据
Z
的条件概率分布;
P(Z|Y,\theta^{(i)}):给定观测数据Y和当前的参数估计\theta^{(i)}下隐变量数据Z的条件概率分布;
P(Z∣Y,θ(i)):给定观测数据Y和当前的参数估计θ(i)下隐变量数据Z的条件概率分布;
def E_step(dataSetArr, alpha0, mu0, sigmod0, alpha1, mu1, sigmod1):
'''
依据当前模型参数,计算分模型k对观数据y的响应度
:param dataSetArr: 可观测数据y
:param alpha0: 高斯模型0的系数
:param mu0: 高斯模型0的均值
:param sigmod0: 高斯模型0的方差
:param alpha1: 高斯模型1的系数
:param mu1: 高斯模型1的均值
:param sigmod1: 高斯模型1的方差
:return: 两个模型各自的响应度
'''
#计算y0的响应度
#先计算模型0的响应度的分子
gamma0 = alpha0 * calcGauss(dataSetArr, mu0, sigmod0)
#模型1响应度的分子
gamma1 = alpha1 * calcGauss(dataSetArr, mu1, sigmod1)
#两者相加为E步中的分布
sum = gamma0 + gamma1
#各自相除,得到两个模型的响应度
gamma0 = gamma0 / sum
gamma1 = gamma1 / sum
#返回两个模型响应度
return gamma0, gamma1
θ ( i + 1 ) = a r g ∗ m a x θ Q ( θ , θ ( i ) ) \theta^{(i+1)} = arg * \mathop{max}\limits_{\theta} Q(\theta,\theta^{(i)}) θ(i+1)=arg∗θmaxQ(θ,θ(i))
def M_step(muo, mu1, gamma0, gamma1, dataSetArr):
mu0_new = np.dot(gamma0, dataSetArr) / np.sum(gamma0)
mu1_new = np.dot(gamma1, dataSetArr) / np.sum(gamma1)
sigmod0_new = math.sqrt(np.dot(gamma0, (dataSetArr - muo)**2) / np.sum(gamma0))
sigmod1_new = math.sqrt(np.dot(gamma1, (dataSetArr - mu1)**2) / np.sum(gamma1))
alpha0_new = np.sum(gamma0) / len(gamma0)
alpha1_new = np.sum(gamma1) / len(gamma1)
#将更新的值返回
return mu0_new, mu1_new, sigmod0_new, sigmod1_new, alpha0_new, alpha1_new
def EM_Train(dataSetList, iter = 500):
'''
根据EM算法进行参数估计
:param dataSetList:数据集(可观测数据)
:param iter: 迭代次数
:return: 估计的参数
'''
#将可观测数据y转换为数组形式,主要是为了方便后续运算
dataSetArr = np.array(dataSetList)
#步骤1:对参数取初值,开始迭代
alpha0 = 0.5; mu0 = 0; sigmod0 = 1
alpha1 = 0.5; mu1 = 1; sigmod1 = 1
#开始迭代
step = 0
while (step < iter):
#每次进入一次迭代后迭代次数加1
step += 1
#步骤2:E步:依据当前模型参数,计算分模型k对观测数据y的响应度
gamma0, gamma1 = E_step(dataSetArr, alpha0, mu0, sigmod0, alpha1, mu1, sigmod1)
#步骤3:M步
mu0, mu1, sigmod0, sigmod1, alpha0, alpha1 = \
M_step(mu0, mu1, gamma0, gamma1, dataSetArr)
#迭代结束后将更新后的各参数返回
return alpha0, mu0, sigmod0, alpha1, mu1, sigmod1
alpha0, mu0, sigmod0, alpha1, mu1, sigmod1 = EM_Train(dataSetList)
print('Parameters predict:')
print('alpha0:%.1f, mu0:%.1f, sigmod0:%.1f, alpha1:%.1f, mu1:%.1f, sigmod1:%.1f' % (
alpha0, mu0, sigmod0, alpha1, mu1, sigmod1))
假设空间(Hypothesis Space)
{ a r g ∗ m a x θ Q ( θ , θ ( i ) ) } \left\{ arg * \mathop{max}\limits_{\theta} Q(\theta,\theta^{(i)}) \right\} {arg∗θmaxQ(θ,θ(i))}
输出
θ \theta θ