我不确定如何使用训练好的高斯混合模型(GMM)对新数据进行预测。例如,我有一些来自三个不同类别(聚类)的标记数据。对于每一类数据点,我都拟合了一个GMM(gm1, gm2和gm3)。假设我们知道每个类别的高斯混合数量(例如,k1=2, k2=1和k3=3),或者可以使用Akaike信息准则(AIC)进行估计(优化)。那么当我得到一些新的数据集时,我如何知道它更可能属于类别1、2还是3?
以下是Matlab脚本展示我的意思:
clc; clf; clear all; close all;%% 创建一些人造训练数据% 1. 聚类1包含两个高斯混合(k1 = 2)rng default; % 为了可重复性mu1 = [1 2];sigma1 = [3 .2; .2 2];mu2 = [-1 -2];sigma2 = [2 0; 0 1];X1 = [mvnrnd(mu1,sigma1,200); mvnrnd(mu2,sigma2,100)];options1 = statset('Display', 'final');k1 = 2;gm1 = fitgmdist(X1, k1, 'Options', options1);% 2. 聚类2包含一个高斯混合(k2 = 1)mu3 = [6 4];sigma3 = [3 .1; .1 4];X2 = mvnrnd(mu3,sigma3,300);options2 = statset('Display', 'final');k2 = 1;gm2 = fitgmdist(X2, k2, 'Options', options2);% 3. 聚类3包含三个高斯混合(k3 = 3)mu4 = [-5 -6];sigma4 = [1 .1; .1 1];mu5 = [-5 -10];sigma5 = [6 .1; .1 1];mu6 = [-2 -15];sigma6 = [8 .1; .1 4];X3 = [mvnrnd(mu4,sigma4,200); mvnrnd(mu5,sigma5,300); mvnrnd(mu6,sigma6,100)];options3 = statset('Display', 'final');k3 = 3;gm3 = fitgmdist(X3, k3, 'Options', options3);% 显示figure,scatter(X1(:,1),X1(:,2),10,'ko'); hold on;ezcontour(@(x,y)pdf(gm1, [x y]), [-12 12], [-12 12]);scatter(X2(:,1),X2(:,2),10,'ko');ezcontour(@(x,y)pdf(gm2, [x y]), [-12 12], [-12 12]);scatter(X3(:,1),X3(:,2),10,'ko');ezcontour(@(x,y)pdf(gm3, [x y]), [-12 12], [-12 12]); hold off;
我们可以得到以下图形:
然后我们得到了一些新的测试数据,例如:
%% 创建一些人造测试数据mut1 = [6.1 3.8];sigmat1 = [3.1 .1; .1 4.2];mut2 = [5.8 4.5];sigmat2 = [2.8 .1; .1 3.8];Xt1 = [mvnrnd(mut1,sigmat1,500); mvnrnd(mut2,sigmat2,100)];figure,scatter(Xt1(:,1),Xt1(:,2),10,'ko');xlim([-12 12]); ylim([-12 12]);
我故意将测试数据设置得与聚类2的数据相似。在使用GMM进行训练后,我们能否以某种方式预测新测试数据的标签?是否有可能得到一些概率结果,例如(p1 = 18%, p2 = 80% 和 p3 = 2%)来预测每个类别的概率。由于我们得到了p2=80%,我们可以进行硬分类,将新测试数据标记为聚类2。
附注:我找到了这个帖子,但对我来说似乎太理论化了 (类似帖子)。如果可以,请在您的回复中加入一些简单的Matlab脚本。
非常感谢。A.
编辑:
由于Amro回复了问题的解决方案,我有了更多的问题。
-
Amro使用整个数据集创建了一个新的GMM,并进行了一些初始化:
% 新GMM的初始参数(结合之前的三个)% (注意PComponents根据每个子集中的数据比例进行归一化)S = struct('mu',[gm1.mu; gm2.mu; gm3.mu], ... 'Sigma',cat(3, gm1.Sigma, gm2.Sigma, gm3.Sigma), ... 'PComponents',[gm1.PComponents*n1, gm2.PComponents*n2, gm3.PComponents*n3]./n);% 在所有实例上训练最终模型opts = statset('MaxIter',1000, 'Display','final');gmm = fitgmdist(X, k, 'Options',opts, 'Start',S);
Amro得到的结果如下所示
这可能不适合我的数据,因为它将我的标记聚类1分开了,并且聚类2与聚类1的一部分混合。这是我试图避免的。
这里我展示的是一个人造的数值示例;然而,在我的实际应用中,它涉及到图像分割问题(例如,聚类1是我的背景图像,聚类2是我想要分离的对象)。然后我试图以某种方式“强制”单独的GMM来拟合单独的类别。如果两个聚类相距甚远(例如,这个例子中的聚类1和聚类3),使用Amro的方法结合所有数据然后进行GMM拟合没有问题。然而,当我们在图像数据上进行训练时,由于分辨率的限制(导致部分体效应),永远无法完美地将背景与对象分开;因此,很可能出现聚类1与聚类2重叠的情况,如图所示。我认为混合所有数据然后进行拟合可能会对新数据的进一步预测造成一些问题,我说的对吗?
然而,经过一番思考后,我现在尝试做的是:
% 结合高斯混合并形成一个新的gmdistributionmuAll = [gm1.mu; gm2.mu; gm3.mu]; sigmaAll = cat(3, gm1.Sigma, gm2.Sigma, gm3.Sigma);gmAll = gmdistribution(muAll, sigmaAll);pt1 = posterior(gmAll, Xt1);
大家觉得怎么样?或者这与Amro的方法等同?如果是的话,有没有方法可以强制我的训练好的GMM分开?
-
我还对使用
posterior
函数的原理有疑问。本质上,我想估计给定GMM拟合的测试数据的可能性。那么为什么我们现在计算后验概率?或者这只是一个命名问题(换句话说,“后验概率”=“可能性”)? -
据我所知,GMM一直被用作无监督方法。甚至有人告诉我GMM是k-means聚类的概率版本。使用这种“有监督”风格使用它是否合适?有推荐的论文或参考资料吗?
再次非常感谢您的回复!A.
回答:
实际上你已经训练了三个GMM模型而不是一个,每个模型本身就是一个混合。通常你会创建一个具有多个组件的GMM,其中每个组件代表一个聚类…
所以在你的情况下,我会创建一个新的GMM模型,使用整个数据集(X1
、X2
和X3
)进行训练,组件数量等于三个GMM中所有组件的总和(即2+1+3 = 6
个高斯混合)。这个模型将使用单独训练的模型的参数进行初始化。
以下是说明的代码(我使用了你在示例中创建的相同变量):
% 每个数据子集中的实例数量n1 = size(X1,1);n2 = size(X2,1);n3 = size(X3,1);% 整个数据集X = [X1; X2; X3];n = n1 + n2 + n3;k = k1 + k2 + k3;% 新GMM的初始参数(结合之前的三个)% (注意PComponents根据每个子集中的数据比例进行归一化)S = struct('mu',[gm1.mu; gm2.mu; gm3.mu], ... 'Sigma',cat(3, gm1.Sigma, gm2.Sigma, gm3.Sigma), ... 'PComponents',[gm1.PComponents*n1, gm2.PComponents*n2, gm3.PComponents*n3]./n);% 在所有实例上训练最终模型opts = statset('MaxIter',1000, 'Display','final');gmm = fitgmdist(X, k, 'Options',opts, 'Start',S);% 在训练数据上显示GMM密度函数line(X(:,1), X(:,2), 'LineStyle','none', ... 'Marker','o', 'MarkerSize',1, 'Color','k')hold onezcontour(@(x,y) pdf(gmm,[x y]), xlim(), ylim())hold offtitle(sprintf('GMM over %d training instances',n))