高斯混合模型GMM---【1】

1.高斯混合模型概念

高斯混合模型(Gaussian Mixture Model)是一种聚类算法,它是多个高斯分布函数的线性组合,通常用于解决同一集合下的数据包含多种不同的分布情况。
高斯混合模型是指具有如下形式的概率分布模型:

其中K为高斯混合模型中成分的个数,g为高斯分布密度,均值是 μ \mu 协方差矩阵是 k \sum{_k} ,另外 ω \omega 是每个成分的权重。
例如如图下所示,是两个高斯分量叠加而成的一维GMM:

则上图中红色的曲线其表达式就为;

以下图片左边部分展示的是两个二维高斯分布的平面图,那么其对应的高斯混合模型在三维视图中,就像下图中的右半部分,有着两个峰。

又或者三个高斯混合模型其叠加后的三维展示图如下所示:

2.高斯混合模型的一个例子

在校园里随机抽取2000个学生,其中有男生也有女生,已知男女生的身高都服从高斯分布,这两个高斯分布的均值和方差我们不知道,另外,由于某种原因,我们也不知道这2000个人中有多少个男生有多少个女生,现在我们要求出这两个分布的均值和标准差,还有其权重。

2.0 注意事项

根据题目的需求,我们需要产生两个高斯分布序列,分别代表男女生的身高。需要注意的是,我们在产生序列的时候必须要在知道男女生各占多少的情况下进行随机生成。但是在求解的过程中,我们必须遵照题意,假设不知道男女生的人数和其各自的均值和方差。然后再对这混合后的2000人序列数据,进行不断地迭代,直到得到的均值和方差趋于平稳。
对于混合前和混合后的数据分别如下图所示:

项目 Value

在图中我们也可以看到,我们生成的女生身高 f e m a l e female 服从于 N ( 160 16 ) N(160,16) ,男生身高 m a l e male 服从于 N ( 180 , 30 ) N(180,30) 。并且其matlab生成该随机序列的代码如下:

%绘制男女生身高的例子
clc
clear all
%男女生共取2000人,女生平均身高160,男生平均身高180
female=160+randn(1,821)*sqrt(16);
male=180+randn(1,1179)*sqrt(30);
people=[female male];
figure(1)
hist(people,150);%画出混合后的频率分布直方图
N=100;
figure(2)
hist(female,N);%画出生成的女性的频率分布直方图
h=findobj(gca,'Type','patch');
set(h,'facecolor','r');hold on;%设置柱形图颜色
hist(male,N);%画出生成的男性的频率分布直方图
title('某校男女生身高的分布直方图');
xlabel('身高/cm');ylabel('人数');hold off ;%坐标轴设置

接下来我们就需要对数据进行不断地迭代,从而使其得到两类分布的最优解。

2.1 Step 1. 初始化参数

对于首次迭代,我们需要提供一下,对于男女的均值方差以及权值之间的初始值设定,否则无法启动迭代。这里我们的初始值的设定,我们只需要我们生活中的常识对其进行一下赋初值即可。无需考虑太多。

正如图上所画的,在以后的介绍中, μ \mu , s i g m a sigma 的颜色不同,代表了性别不同,此处我们以蓝色代表男生的,粉色代表女生的。
例如我们在这里的,我假设男女生人数一样多,于是我就对初值进行了如下赋值:

%前提是不知道男女生分布的均值和方差的。
g_mu1=170;g_sigma1=10;g_w1=0.5;%男生的
g_mu2=160;g_sigma2=5;g_w2=0.5;%女生的

2.2 计算每个身高 h i h_i 在男分布中的响应 R R

通过下面的公式,我们要对我们的2000个混合后的身高数据,利用我们刚刚赋的初值来计算一下每个身高 h i h_i 在男分布中的响应 R R 。所以此处也就一共有2000个响应值。

在这里或许大家会疑惑,公式中的 g ( h i μ , σ ) g(h_i|\mu,\sigma) 代表的是啥,其实这是一维高斯函数的密度函数,对于我们的这个例子而言,其详细的表达式如下:

g ( h i μ , σ ) = 1 2 π σ e ( h i μ ) 2 2 σ 2 g(h_i|\mu,\sigma)=\frac{1}{\sqrt{2\pi}\sigma}e^{-\frac{(h_i-\mu)^2}{2\sigma^2}}
好了计算完身高男生的身高 h i h_i 在男分布中的响应 R R ,我们再来计算一下女生的 h i h_i 在男分布中的响应 R R ,其求解公式类比于前边介绍到的男生的求解:

同样,也是得到2000个响应值。

2.3 更新男女生分布的期望值 μ \mu

由于之前的男女生的期望值 μ \mu 都是我们凭着主观经验猜测的,所以我们需要对该值进行迭代更新,下面我先介绍男生身高期望值的更新公式。

这里的 R i R_i 值和 h i h_i 值都是我们已知的数据,其中 R i R_i 是我们上一步所求, h i h_i 是我们已知的混合后的2000个身高序列中的一个。
如果我们对于上式不是特别理解的话,我们可以将其一步不拆解开来,方便我们理解。详见下图:

通过上式的拆解展示,我们可以看到,新更新的均值是和之前的均值有关系的。
通过此方式更新完均值之后,我们便可同理求得女生身高的更新后的数据,具体其表达式如下所示:

最后我们求得的均值很明显是一个值。

2.4 更新男女生分布的方差 σ 2 \sigma^2

原因同上边一样,我们要通过如下公式更新一下男生分布的方差,其求解公式如下所示:

需要注意的是,我们在这里求得的是更新后的方差,而别的地方使用的是标准差,所以在这里编程的时候要注意一下。另外,女生的更新方式类似:

2.5 更新权值 ω 1 , ω 2 \omega_1,\omega_2

男生分布的权值的更新如下:

类似的,女生分布的权值的更新如下:

2.6 仿真效果

在迭代十次之后,我们就可以看到,其迭代结果已趋于稳定,效果显示如下:

在这里插入图片描述 Value

在上图中我们可以看到,随着迭代次数的增加,我们的男女的权重系数也都趋于稳定,并且我们取最后一次迭代的结果,做出男女身高的高斯概率曲线。我们 可以拿该曲线迭代出的结果与之前的结果进行比较,可知其迭代精度还是可以的。

2.7 高斯混合模型不同权值的比较

对于不同的迭代结果,我以动图的形式来展示如下,在不同的权值下,其叠加后的高斯混合模型图样也是不一样的,如下所示:
在这里插入图片描述

2.8 三个一维的高斯分布

不同类别权重随迭代次数的变化:
在这里插入图片描述
迭代15次后得知的三个高斯正态分布的概率密度曲线,
在这里插入图片描述
高斯混合模型的随迭代次数的变化而变化图形
在这里插入图片描述

3.matlab源码

3.1 迭代更新的函数封装(matlab)

由于要使用不断迭代的方式来不断求取新的均值方差权值,以期使得迭代的结果更加接近真实值,于是我对于这部分的代码进行了一下封装,将其封装为一个loop.m文件。其内容具体如下:

文件名称:loop.m
function [ mu1_new,sigma1_new,w1_new,mu2_new,sigma2_new,w2_new ] = loop(male,female,g_mu1,g_sigma1,g_w1,g_mu2,g_sigma2,g_w2 )
%UNTITLED 此处显示有关此函数的摘要
%   此处显示详细说明
%Step 1.首先根据经验来分别设置男女生的均值、方差和权值
% g_mu1=175;g_sigma1=10;g_w1=0.5;%男生的
% g_mu2=158;g_sigma2=10;g_w2=0.5;%女生的

%Step 2. 
%计算男的身高在男分布中的响应R1i
%计算女的身高在男分布中的响应R2i
people=[female male];
R1=zeros(1,2000);
R2=zeros(1,2000);
for i=1:2000
    px1=g_w1*pdf('norm',people(i),g_mu1,g_sigma1);
    px2=g_w2*pdf('norm',people(i),g_mu2,g_sigma2);
    R1(i)=px1/(px1+px2);
    R2(i)=px2/(px1+px2);
end

%Step 3.
%更新男、女生身高分布的期望mu

sum1=0;
sum2=0;
for i=1:2000
    sum1=sum1+R1(i)*people(i);
    sum2=sum2+R2(i)*people(i);
end
sum11=sum(R1);
sum22=sum(R2);
mu1_new=sum1/sum11;%得出男生的新均值
mu2_new=sum2/sum22;%得出女生的新均值

%Step 4.
%更新男、女生身高分布的标准差sigma
sum1=0;
sum2=0;
for i=1:2000
    sum1=sum1+R1(i)*(people(i)-mu1_new)^2;
    sum2=sum2+R2(i)*(people(i)-mu2_new)^2;
end
sigma1_new=(sum1/sum11)^0.5;%得出男生的新标准差
sigma2_new=(sum2/sum22)^0.5;%得出女生的新标准差


%Step 5.
%更新权值
w1_new=sum11/2000;
w2_new=sum22/2000;

end

3.2 主函数实现高斯混合模型GMM

该函数是实现整个这个实例的matlab代码主函数,其内容如下:

文件名称:GMM.m
%绘制男女生身高的例子
clc
clear all
%男女生各取2000人,女生平均身高163,男声平均身高180
female=160+randn(1,821)*sqrt(16);
male=180+randn(1,1179)*sqrt(30);
people=[female male];
figure(1)
hist(people,150);%画出混合后的频率分布直方图
N=100;
figure(2)
hist(female,N);%画出生成的女性的频率分布直方图
h=findobj(gca,'Type','patch');
set(h,'facecolor','r');hold on;%设置柱形图颜色
hist(male,N);%画出生成的男性的频率分布直方图
title('某校男女生身高的分布直方图');
xlabel('身高/cm');ylabel('人数');hold off ;%坐标轴设置

%以下通过五个步骤开始构建高斯混合模型

%Step 1.首先根据经验来分别设置男女生的均值、方差和权值
%前提是不知道男女生分布的均值和方差的。
g_mu1=170;g_sigma1=10;g_w1=0.5;%男生的
g_mu2=160;g_sigma2=5;g_w2=0.5;%女生的

times=10;%设置迭代次数
result=zeros(times,6);%定义一个数组来存储每次的迭代结果
result(1,1)=g_mu1;result(1,2)=g_sigma1;%以下
result(1,3)=g_w1;result(1,4)=g_mu2;
result(1,5)=g_sigma2;result(1,6)=g_w2;%以上将result的第一行设置为初始值

for i=1:times-1
    %调用自己的迭代函数loop来实现迭代计算
   [ mu11_new,sigma11_new,w11_new,mu22_new,sigma22_new,w22_new ]=loop(male,female,result(i,1),result(i,2),result(i,3),result(i,4),result(i,5),result(i,6));
    result(i+1,1)=mu11_new;result(i+1,2)=sigma11_new;result(i+1,3)=w11_new;%将每次迭代的结果存入result
    result(i+1,4)=mu22_new;result(i+1,5)=sigma22_new;result(i+1,6)=w22_new ;%当前迭代完成
end
result    % 输出每次迭代结果
figure(3)
%plot(result(:,3),'linewidth',1.5);%画出男生的权重迭代历史
xi=1:0.4:times;
xx=interp1(result(:,3),xi, 'spline');
plot(xx,'linewidth',1.5);%画出男生的权重迭代历史
hold on ;grid on;
yy=interp1(result(:,6),xi, 'spline');
plot(yy,'r','linewidth',1.5);%画出女生权重迭代历史
legend('男生权重变化','女生权重变化','location','northeast');%坐标轴设置
title('男女生权重随迭代次数的变化');
xlabel('迭代次数');ylabel('权重值');axis([1 times 0 1]);%坐标轴设置


%开始分别求取出男女生的概率密度函数
%在刚刚的迭代结果中取出男女生的分别的mu和sigma
%男生而言需要求出mu1,sigma1,w1
%女生而言需要求取mu2,sigma2,w2
mu1=result(times,1);
sigma1=result(times,2);
mu2=result(times,4);
sigma2=result(times,5);
figure(4);
%画出男生的概率密度曲线
inter_x=linspace(140,210,500)';
inter_y=normpdf(inter_x,mu1,sigma1);
plot(inter_x,inter_y,'linewidth',1.5);
hold on;
%画出女生的概率密度曲线
inter_yy=normpdf(inter_x,mu2,sigma2);
plot(inter_x,inter_yy,'m','linewidth',1.5)
grid on;
legend('男生','女生');title('男女生身高的概率密度曲线');
xlabel('身高/cm');ylabel('概率');hold off;%坐标轴设置


%%此部分开始画高斯混合模型的图像
x =140:0.1:210 ;
y1 = normpdf(x,mu1,sigma1);%定义第1个高斯密度曲线
y2 = normpdf(x,mu2,sigma2);%定义第2个高斯密度曲线
figure(5)
plot(x,y1,'--b','linewidth',1.5);%画出第1个高斯概率密度曲线的图像
hold on;
plot(x,y2,'--g','linewidth',1.5);%画出第2个高斯概率密度曲线的图像
title('两个一维高斯分布HMM模型');xlabel('X');ylabel('概率密度');
% axis([-8 10 0 0.5]);
grid on;%坐标轴设置
tex=text(180,0.1,'当前W1数值为:','FontSize',14,'FontWeight','demi');%图中显示权重
rate=result(:,3)%定义一个权重
c=colormap(lines(times));%定义times条不同颜色的线条
for i=1:times
   pause(0.1);%延时函数
   y3=rate(i)*y1+(1-rate(i))*y2%对两个高斯概率密度图像进行加权
   p2=plot(x,y3,'color',c(i,:),'linewidth',1.5);%绘画加权后的图像
   num=num2str(rate(i));%将当前第一个高斯概率所用的权重值转为字符串类型
   tex1=text(203,0.1,num,'FontSize',14,'FontWeight','demi','color','r');%显示当前权重值
   pause(0.3);%延时函数
   if(i<times)
       delete(tex1);%删除当前权重
       delete(p2);  %删除当前加权后图像
   end
end
hold off
发布了44 篇原创文章 · 获赞 37 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_38468077/article/details/103264309