scipy 多个多元高斯函数最大似然交集的求解

ilmyapht  于 2022-11-10  发布在  其他
关注(0)|答案(1)|浏览(145)

是否有一种高效的方法可以直接求解多个多变量高斯最可能的交点(X, Y)**?
我见过一个few posts here,它问如何求解两个高斯分布之间的交集--这个概念对我来说很熟悉。现在对我来说,除了一次迭代和求解两个分布之外,这个概念并不明显。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

mus = [np.array([[0.3],[0.7]]), 
       np.array([[0.3],[0.2]]), 
       np.array([[1.5],[0.6]])]        

covs = [np.array([[0.85, 0.3], [0.3, 0.25]]), 
        np.array([[0.7, -0.41], [-0.41, 0.25]]), 
        np.array([[0.5, 0.15], [0.15, 0.15]])]

cmaps = ["Reds", "Blues", "Greens"]

for m, cov, c in zip(mus, covs, cmaps):

    cov_inv = np.linalg.inv(cov) 
    cov_det = np.linalg.det(cov)

    x = np.linspace(-3, 3)
    y = np.linspace(-3, 3)
    X,Y = np.meshgrid(x,y)
    coe = 1.0 / ((2 * np.pi)**2 * cov_det)**0.5
    Z = coe * np.e**(-0.5 * (cov_inv[0,0]*(X-m[0])**2 + (cov_inv[0,1] + cov_inv[1,0])*(X-m[0])*(Y-m[1]) + cov_inv[1,1]*(Y-m[1])**2))
    plt.contour(X,Y,Z, cmap = c)
5lwkijsr

5lwkijsr1#

你可以做得比一次在两个解决方案之间迭代要好得多。(x,y)点,则所有3条曲线都具有Z值,并且在3向相交点处,它们都相等(或在公差范围内)。而在其他点,如果取曲线的最低Z,并向中心移动(mu_x,mu_y),您正在朝着改进的方向前进。
下面是一个迭代算法。当然,在可能的增强方面,还有一些肉在骨头上。值得注意的是,你可以很容易地为停止条件加入一个“公差”,或者对2个较低的z值进行加权平均,而不仅仅是最低的z值,以获得运动矢量,或者用一个更大的步长进行修补。
无论如何,对于许多不同的测试起点,这收敛得非常快。

代码:
import numpy as np
import matplotlib.pyplot as plt

class Curve:
    # a convenience so we can avoid recomputations
    def __init__(self, mu, cov_inv, cov_det):
        self.mu = mu
        self.cov_inv = cov_inv
        self.cov_det = cov_det
        self.coe = 1.0 / ((2 * np.pi)**2 * cov_det)**0.5

    def z(self, x, y):
        Z = self.coe * np.e**(-0.5 * (self.cov_inv[0,0]*(x-self.mu[0])**2 + \
            (self.cov_inv[0,1] + self.cov_inv[1,0])*(x-self.mu[0])*(y-self.mu[1]) + self.cov_inv[1,1]*(y-self.mu[1])**2))
        return Z

mus = [np.array([[0.3],[0.7]]), 
       np.array([[0.3],[0.2]]), 
       np.array([[1.5],[0.6]])]        

covs = [np.array([[0.85, 0.3], [0.3, 0.25]]), 
        np.array([[0.7, -0.41], [-0.41, 0.25]]), 
        np.array([[0.5, 0.15], [0.15, 0.15]])]

cmaps = ["Reds", "Blues", "Greens"]

curves = []
for m, cov, c in zip(mus, covs, cmaps):

    cov_inv = np.linalg.inv(cov) 
    cov_det = np.linalg.det(cov)

    x = np.linspace(-3, 3)
    y = np.linspace(-3, 3)
    X,Y = np.meshgrid(x,y)
    coe = 1.0 / ((2 * np.pi)**2 * cov_det)**0.5
    Z = coe * np.e**(-0.5 * (cov_inv[0,0]*(X-m[0])**2 + (cov_inv[0,1] + cov_inv[1,0])*(X-m[0])*(Y-m[1]) + cov_inv[1,1]*(Y-m[1])**2))
    plt.contour(X,Y,Z, cmap = c)
    curves.append(Curve(m, cov_inv, cov_det))

# iterative algorithm...

pos = np.array((-1,2))
step_size = 0.1
num_steps = 100
footprints = [pos,]

for step in range(num_steps):
    zs = [ (curves[i].z(*pos), i) for i in range(len(curves))]
    zs.sort()  # sort by z value, lowest will be first
    c = curves[zs[0][1]]  # the curve to move toward
    vec = c.mu.T - pos
    move_vec = vec * (step_size/np.linalg.norm(vec))
    print(f'move: {move_vec} towards curve {zs[0][1]}')
    pos = pos + move_vec
    pos = pos.flatten()
    # check to see if we have backtracked, if so, shorten the step
    if len(footprints) > 1 and np.linalg.norm(pos - footprints[-2]) < step_size:
        #print(f'norm: {np.linalg.norm(pos-footprints[-2])}')
        step_size *= 0.5
    footprints.append(pos)

plt.plot([t[0] for t in footprints], [t[1] for t in footprints], c='k', lw=2)
plt.show()

地块:

相关问题