我编写了一个小脚本来模拟EM算法并可视化其迭代步骤。然而,在第5次迭代之后,当试图绘制更新的估计双变量高斯分布时,它会停止。轮廓抛出一个错误试图绘制多元高斯
我怀疑我的协方差矩阵有什么可疑之处,但我并不确定。如果我评论等高线图,脚本运行良好,并且按照它应有的工作方式工作(但当然,遵循估计分布的演变将会很好)。任何帮助,将不胜感激。
import numpy as np
import scipy.stats as sp
import matplotlib.pyplot as plt
from matplotlib.mlab import bivariate_normal
def expectationMaximization():
# define multivariate gaussian distributions and generate observations
u1 = [-1.5, -1.5]
cov1 = [[0.2, 0.4],
[0, 0.1]]
u2 = [1, 1]
cov2 = [[0.3, 0.4],
[0, 0.3]]
samples = 1000
x1, y1 = np.random.multivariate_normal(u1, cov1, samples // 2).T
x2, y2 = np.random.multivariate_normal(u2, cov2, samples // 2).T
x = np.concatenate([x1, x2])
y = np.concatenate([y1, y2])
points = np.concatenate([np.column_stack((x1, y1)),
np.column_stack((x2, y2))])
# initialization of classifier models
uk1 = np.array([-1.5, 1])
covk1 = np.array([[1, 0], [0, 1]])
uk2 = np.array([1.5, -1])
covk2 = np.array([[1, 0], [0, 1]])
w = np.array([1., 1.])
gamma = np.zeros((2, samples))
# sim loop
for idx in range(9):
##########################################################
# expectation #
##########################################################
# update gamma
gamma[0] = (w[0] * sp.multivariate_normal.pdf(points, uk1, covk1)/
(w[0] * sp.multivariate_normal.pdf(points, uk1, covk1) +
w[1] * sp.multivariate_normal.pdf(points, uk2, covk2)))
gamma[1] = (w[1] * sp.multivariate_normal.pdf(points, uk2, covk2)/
(w[0] * sp.multivariate_normal.pdf(points, uk1, covk1) +
w[1] * sp.multivariate_normal.pdf(points, uk2, covk2)))
##########################################################
# plot #
##########################################################
plt.subplot(3, 3, idx + 1)
plt.title('Iteration {}'.format(idx + 1))
axes = plt.gca()
axes.set_xlim([-3, 3])
axes.set_ylim([-3, 3])
# setup grid for bivariate gaussian plot (only needed once)
if idx < 1:
xmin, xmax = axes.get_xlim()
ymin, ymax = axes.get_ylim()
delta = 0.1
xticks = np.arange(xmin, xmax, delta)
yticks = np.arange(ymin, ymax, delta)
xmesh, ymesh = np.meshgrid(xticks, yticks)
# update mesh values
z1 = bivariate_normal(xmesh, ymesh, covk1[0, 0], covk1[1, 1],
uk1[0], uk1[1], covk1[0, 1])
z2 = bivariate_normal(xmesh, ymesh, covk2[0, 0], covk2[1, 1],
uk2[0], uk2[1], covk2[0, 1])
z = (z1 - z2) * 10
# plot pdf map and sample points
plt.contour(xmesh, ymesh, z)
plt.scatter(x, y, c=(gamma[0] - gamma[1]) * 10)
plt.grid(True)
##########################################################
# maximization #
##########################################################
# update means
uk1[0] = sum(gamma[0] * x)/sum(gamma[0])
uk1[1] = sum(gamma[0] * y)/sum(gamma[0])
uk2[0] = sum(gamma[1] * x)/sum(gamma[1])
uk2[1] = sum(gamma[1] * y)/sum(gamma[1])
# update covariance matrices
# calc all distances
dist1 = points - uk1[None, :]
dist2 = points - uk2[None, :]
# calc all outer products
matrixSchaar1 = np.einsum('...i,...j->...ij', dist1, dist1)
matrixSchaar2 = np.einsum('...i,...j->...ij', dist2, dist2)
# calculate sum product of matrices and gammas
covk1 = ((matrixSchaar1 * gamma[0][:, None, None]).sum(axis=0)/
sum(gamma[0]))
covk2 = ((matrixSchaar2 * gamma[1][:, None, None]).sum(axis=0)/
sum(gamma[1]))
# update w
w[0] = sum(gamma[0])/len(gamma[0])
w[1] = sum(gamma[1])/len(gamma[1])
def main():
expectationMaximization()
plt.show()
if __name__ == "__main__":
main()
回溯:
/usr/lib64/python3.5/site-packages/matplotlib/mlab.py:1926: RuntimeWarning: invalid value encountered in sqrt
denom = 2*np.pi*sigmax*sigmay*np.sqrt(1-rho**2)
Traceback (most recent call last):
File "bsp4.py", line 120, in <module>
main()
File "bsp4.py", line 115, in main
expectationMaximization()
File "bsp4.py", line 76, in expectationMaximization
plt.contour(xmesh, ymesh, z)
File "/usr/lib64/python3.5/site-packages/matplotlib/pyplot.py", line 2766, in contour
ret = ax.contour(*args, **kwargs)
File "/usr/lib64/python3.5/site-packages/matplotlib/__init__.py", line 1815, in inner
return func(ax, *args, **kwargs)
File "/usr/lib64/python3.5/site-packages/matplotlib/axes/_axes.py", line 5644, in contour
return mcontour.QuadContourSet(self, *args, **kwargs)
File "/usr/lib64/python3.5/site-packages/matplotlib/contour.py", line 1424, in __init__
ContourSet.__init__(self, ax, *args, **kwargs)
File "/usr/lib64/python3.5/site-packages/matplotlib/contour.py", line 864, in __init__
self._process_levels()
File "/usr/lib64/python3.5/site-packages/matplotlib/contour.py", line 1202, in _process_levels
self.vmin = np.amin(self.levels)
File "/usr/lib64/python3.5/site-packages/numpy/core/fromnumeric.py", line 2359, in amin
out=out, keepdims=keepdims)
File "/usr/lib64/python3.5/site-packages/numpy/core/_methods.py", line 29, in _amin
return umr_minimum(a, axis, None, out, keepdims)
ValueError: zero-size array to reduction operation minimum which has no identity
很高兴你发现了这个问题!随意接受你的答案是正确的。 – lanery