使用EM算法计算混合高斯模型的参数,及其可视化

转载请标明作者

本文主要使用了EM算法计算隐变量,计算使用的是假数据,使用了三个高斯进行混合,由于时间,代码只是进行了部分优化,所以运算有点慢,还有图的显示以后有时间再改吧,代码如下:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from scipy import stats
np.random.seed(1234)
x_plot_1,x_plot_2=np.mgrid[-10:10:50j,-10:10:50j]
x_plot=np.stack((x_plot_1,x_plot_2),axis=2)
u=[[-5,-3],[3,-1],[-3,5]]#三个二元高斯的均值
#真实数据的均值,方差和alpha值
sigma=[np.identity(2),np.diag([2,3]),np.array([[2,1],[1,2]])]#三个高斯的方差
#data1=np.random.multivariate_normal()
alpha=[0.1,0.5,0.4]
data_num=600
#上面是混合高斯的所有参数
#下面开始制造假的的数据
def fake_data_gen(u,sigma,alpha,number):
    norm_list=[]
    data_list=[]
    for ga_par in zip(u,sigma,alpha):
        norm=stats.multivariate_normal(ga_par[0],ga_par[1])
        norm_list.append(norm)
    for i in range(number):
        rand=np.random.uniform(0,1)
        if i%200==0:
            print("have generrate {} samples".format(i))
        if rand<=alpha[0]:
            data=norm_list[0].rvs(1)
        elif alpha[0]<rand<=(1-alpha[2]):
            data=norm_list[1].rvs(1)
        else:
            data=norm_list[2].rvs(1)
        data_list.append(data)
    return np.array(data_list)
data=fake_data_gen(u,sigma,alpha,data_num)
#画出假数据的散点图
def plot_mygraph(u,sigma):
    plt.cla()
    plt.scatter(data[:, 0], data[:, 1])
    for i in range(3):
        pdf_x = stats.multivariate_normal(mean=u[i], cov=sigma[i]).pdf(x_plot)
        plt.contour(x_plot_1,x_plot_2,pdf_x)


#初始化所有的参数,u,sigma,alpha,为以后的迭代做准备
u=np.array([[1,1],[3,3],[6,6]])
sigma=np.array([np.identity(2),np.identity(2),np.identity(2)])
alpha=np.array([0.5,0.1,0.4])
#开始迭代
#是哪个分布的后验概率
def poserier_vec_sum(u,sigam,data,l):
    pdf_data_l=stats.multivariate_normal(u[l],sigma[l]).pdf(data)
    sum_data=0
    for i in range(3):
        pdf_data_i=stats.multivariate_normal(u[i],sigma[i]).pdf(data)
        sum_data+=pdf_data_i
    sum_data=pdf_data_l/sum_data
    return sum(sum_data)
def posterier(u,sigam,x_i,l):
    pdf_x_i=stats.multivariate_normal(u[l],sigma[l]).pdf(x_i)
    p_x_sum=sum([stats.multivariate_normal(u[i],sigma[i]).pdf(x_i) for i in range(3)])
    return  pdf_x_i/p_x_sum

def com_alpha(u,sigam,l,data,num):
    sum1=poserier_vec_sum(u,sigma,data,l)
    return sum1/(num)
def com_u(u,sigma,l,data):
    sum1 = poserier_vec_sum(u, sigma, data, l)
    sum2=0
    for x_i in (data):
        sum2+=x_i*posterier(u, sigma, x_i, l)
    return sum2/sum1
def com_sigma(new_u,u,sigma,l,data):
    sum2=0
    sum1 = poserier_vec_sum(u, sigma, data, l)
    for x_i in data:
        x_i_u=np.reshape(x_i,(1,2))-np.reshape(new_u[l],(1,2))
        x_i_u_T=np.reshape(x_i,(2,1))-np.reshape(new_u[l],(2,1))
        sum2+=np.matmul(x_i_u_T,x_i_u)*posterier(u,sigma,x_i,l)
    return sum2/sum1
def gussian_mixture_iter(u,sigma,alpha,data,iter_num):
    for i in range(iter_num):
        plot_mygraph(u, sigma)
        for l in range(3):
            alpha[l]=com_alpha(u,sigma,l,data,data_num)
        alpha = alpha / sum(alpha)
        new_u=[]
        for l in range(3):
            u_tmp=com_u(u,sigma,l,data)
            new_u.append(u_tmp)
        sigma_list=[]
        for l in range(3):
            sigma_tmp=com_sigma(new_u,u,sigma,l,data)
            sigma_list.append(sigma_tmp)
        u=new_u
        sigma=sigma_list
        alpha = alpha / sum(alpha)

        if i%1==0:
            print("第{}次迭代均值为:{}".format(i,u))
            print("第{}次迭代方差为:{}".format(i,sigma))
            print("第{}次迭代alpha为:{}".format(i, alpha))
        plt.show()
    return u,sigma,alpha
u,sigma,alpha=gussian_mixture_iter(u,sigma,alpha,data,100)



,第一次初始化后的图像为:

第二次地迭代:

第三次迭代:

第四次迭代:

第6次迭代:

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用EM算法计算混合高斯分布的MATLAB代码示例: ```matlab % 设置参数 K = 2; % 混合高斯分布中高斯分布的个数 N = 500; % 样本数量 D = 2; % 样本特征维度 % 生成样本 mu_true = [1 2;-2 -3]; % 真实高斯分布的均值 sigma_true = cat(3,[2 0;0 0.5],[0.5 0;0 1]); % 真实高斯分布的协方差矩阵 alpha_true = [0.4,0.6]; % 真实高斯分布的权重 x = zeros(N,D); for i = 1:N k = randi(K); x(i,:) = mvnrnd(mu_true(k,:),sigma_true(:,:,k)); end % EM算法计算混合高斯分布 alpha = ones(1,K)./K; % 初始化高斯分布的权重 mu = rand(K,D).*range(x)+min(x); % 初始化高斯分布的均值 sigma = repmat(eye(D),[1,1,K]); % 初始化高斯分布的协方差矩阵 gamma = zeros(N,K); % 初始化样本属于每个高斯分布的后验概率 log_likelihood = -inf; % 初始化对数似然函数值 for iter = 1:100 % E步:计算样本属于每个高斯分布的后验概率 for k = 1:K gamma(:,k) = alpha(k)*mvnpdf(x,mu(k,:),sigma(:,:,k)); end gamma = gamma./sum(gamma,2); % M步:更新高斯分布的参数 Nk = sum(gamma,1); alpha = Nk./N; mu = gamma'*x./Nk'; for k = 1:K x_centered = x-mu(k,:); sigma(:,:,k) = x_centered'*diag(gamma(:,k))*x_centered./Nk(k); end % 计算对数似然函数值 log_likelihood_new = sum(log(sum(gamma.*repmat(alpha,[N,1]),2))); if abs(log_likelihood_new-log_likelihood) < 1e-6 % 判断收敛 break; end log_likelihood = log_likelihood_new; end % 可视化结果 figure; scatter(x(:,1),x(:,2),10,gamma(:,1),'filled'); hold on; scatter(mu(:,1),mu(:,2),50,'k','filled'); contour(mu_true(:,1),mu_true(:,2),mvnpdf([xx(:),yy(:)],mu_true(1,:),sigma_true(:,:,1)),[0.1,0.5,0.9],'k'); contour(mu_true(:,1),mu_true(:,2),mvnpdf([xx(:),yy(:)],mu_true(2,:),sigma_true(:,:,2)),[0.1,0.5,0.9],'k'); title('EM算法计算混合高斯分布'); xlabel('x_1'); ylabel('x_2'); legend('数据','高斯分布均值','真实高斯分布1','真实高斯分布2'); ``` 其中,`mu_true`、`sigma_true`和`alpha_true`为真实的高斯分布的参数,`x`为生成的样本数据。在算法计算完成后,可以绘制样本数据和计算出的高斯分布的均值,以及真实高斯分布的轮廓线,以便比较它们的相似性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值