HMM study:认识混合高斯模型与EM算法(附Python仿真)

混合高斯模型

Gaussian Mixed Model 表示多个高斯分布的线性组合,设有随机变量 X \textbf{X} X,则混合高斯模型表示如下 p ( x ) = ∑ k = 1 K π k N ( x / μ k , ∑ k ) p(\textbf{x})=\sum_{k=1}^K \pi_kN(x/\mu_k,\sum_k) p(x)=k=1KπkN(x/μk,k)其中 π k \pi_k πk可以认为是高斯分布的权重, N ( x / μ k , ∑ k ) N(x/\mu_k,\sum_k) N(x/μk,k)表示第 k k k个高斯分量。

EM(expectation maximization)期望极大算法

这篇写得太好了在此保存
以GMM为例,已知样本来自GMM,我们需要通过观测样本对GMM的权重 π \pi π,各个高斯模型的均值和方差 μ , ∑ \mu,\sum μ,进行估计。此时思考HMM模型要解决的第一个问题:已知观测值和多个HMM模型,哪个HMM模型最优有可能产生这个观测? 解决这个问题只需要代入模型求解出现该观测的概率,然后选择概率最大的模型即可。
但是混合高斯模型不能直接使用前向算法解决,因为模型并不是已知,我们需要确定模型的参数,且参数不是从已知的模型中进行选择,而是对未知的参数进行拟合。
EM迭代过程:
假设给定一个GMM ( π 0 , u 0 , ∑ 0 ) (\pi_0,u_0,\sum_0) (π0,u0,0),根据该模型对当前的样本划分类别(即每个样本属于哪个高斯分布)。
样本划分完毕,求个各高斯分布产生该样本的概率,并且表示整个采样数据产生的概率,然后最大化采样数据概率。从而优化GMM的参数
如图,来自上述推荐博客
HMM study:认识混合高斯模型与EM算法(附Python仿真)_第1张图片

Python仿真

代码来自网络,侵删

import math
import copy
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D


# 生成随机数据,4个高斯模型
def generate_data(sigma, N, mu1, mu2, mu3, mu4, alpha):
    global X  # 可观测数据集
    X = np.zeros((N, 2))  # 初始化X,2行N列。2维数据,N个样本
    X = np.matrix(X)
    global mu  # 随机初始化mu1,mu2,mu3,mu4
    mu = np.random.random((4, 2))
    mu = np.matrix(mu)
    global excep  # 期望第i个样本属于第j个模型的概率的期望
    excep = np.zeros((N, 4))
    global alpha_  # 初始化混合项系数
    alpha_ = [0.25, 0.25, 0.25, 0.25]
    for i in range(N):
        if np.random.random(1) < 0.1:  # 生成0-1之间随机数
            X[i, :] = np.random.multivariate_normal(mu1, sigma, 1)  # 用第一个高斯模型生成2维数据
        elif 0.1 <= np.random.random(1) < 0.3:
            X[i, :] = np.random.multivariate_normal(mu2, sigma, 1)  # 用第二个高斯模型生成2维数据
        elif 0.3 <= np.random.random(1) < 0.6:
            X[i, :] = np.random.multivariate_normal(mu3, sigma, 1)  # 用第三个高斯模型生成2维数据
        else:
            X[i, :] = np.random.multivariate_normal(mu4, sigma, 1)  # 用第四个高斯模型生成2维数据

    print("可观测数据:\n", X)  # 输出可观测样本
    print("初始化的mu1,mu2,mu3,mu4:", mu)  # 输出初始化的mu


def e_step(sigma, k, N):
    global X
    global mu
    global excep
    global alpha_
    for i in range(N):
        denom = 0
        for j in range(0, k):
            denom += alpha_[j] * math.exp(-(X[i, :] - mu[j, :]) * sigma.I * np.transpose(X[i, :] - mu[j, :])) / np.sqrt(
                np.linalg.det(sigma))  # 分母
        for j in range(0, k):
            numer = math.exp(-(X[i, :] - mu[j, :]) * sigma.I * np.transpose(X[i, :] - mu[j, :])) / np.sqrt(
                np.linalg.det(sigma))  # 分子
            excep[i, j] = alpha_[j] * numer / denom  # 求期望
    print("隐藏变量:\n", excep)


def m_step(k, N):
    global excep
    global X
    global alpha_
    for j in range(0, k):
        denom = 0  # 分母
        numer = 0  # 分子
        for i in range(N):
            numer += excep[i, j] * X[i, :]
            denom += excep[i, j]
        mu[j, :] = numer / denom  # 求均值
        alpha_[j] = denom / N  # 求混合项系数


if __name__ == '__main__':
    iter_num = 1000  # 迭代次数
    N = 500  # 样本数目
    k = 4  # 高斯模型数
    probility = np.zeros(N)  # 混合高斯分布
    u1 = [5, 35]
    u2 = [30, 40]
    u3 = [20, 20]
    u4 = [45, 15]
    sigma = np.matrix([[30, 0], [0, 30]])  # 协方差矩阵
    alpha = [0.1, 0.2, 0.3, 0.4]  # 混合项系数
    generate_data(sigma, N, u1, u2, u3, u4, alpha)  # 生成数据
    # 迭代计算
    for i in range(iter_num):
        err = 0  # 均值误差
        err_alpha = 0  # 混合项系数误差
        Old_mu = copy.deepcopy(mu)
        Old_alpha = copy.deepcopy(alpha_)
        e_step(sigma, k, N)  # E步
        m_step(k, N)  # M步
        print("迭代次数:", i + 1)
        print("估计的均值:", mu)
        print("估计的混合项系数:", alpha_)
        for z in range(k):
            err += (abs(Old_mu[z, 0] - mu[z, 0]) + abs(Old_mu[z, 1] - mu[z, 1]))  # 计算误差
            err_alpha += abs(Old_alpha[z] - alpha_[z])
        if (err <= 0.001) and (err_alpha < 0.001):  # 达到精度退出迭代
            print(err, err_alpha)
            break
    # 可视化结果

    # 画分类好的数据
    plt.subplot(222)
    plt.title('classified data through EM')
    order = np.zeros(N)
    color = ['b', 'r', 'k', 'y']
    for i in range(N):
        for j in range(k):
            if excep[i, j] == max(excep[i, :]):
                order[i] = j  # 选出X[i,:]属于第几个高斯模型
            probility[i] += alpha_[int(order[i])] * math.exp(
                -(X[i, :] - mu[j, :]) * sigma.I * np.transpose(X[i, :] - mu[j, :])) / (
                                        np.sqrt(np.linalg.det(sigma)) * 2 * np.pi)  # 计算混合高斯分布
        plt.scatter(X[i, 0], X[i, 1], c=color[int(order[i])], s=25, alpha=0.4, marker='o')  # 绘制分类后的散点图
    # 绘制三维图像
    ax = plt.subplot(223, projection='3d')
    plt.title('3d view')
    for i in range(N):
        ax.scatter(X[i, 0], X[i, 1], probility[i], c=color[int(order[i])])
    plt.show()

你可能感兴趣的:(机器学习)