📄 gaussmix.m
字号:
function [m,v,w,g,f,pp,gg]=gaussmix(x,c,l,m0,v0,w0)
%GAUSSMIX fits a gaussian mixture pdf to a set of data observations [m,v,w,g,f]=(x,c,l,m0,v0,w0)
%
% Inputs: n data values, k mixtures, p parameters, l loops
%
% X(n,p) Input data vectors, one per row.
% c(1) Minimum variance of normalized data (Use [] to take default value of 1/n^2)
% L The integer portion of l gives a maximum loop count. The fractional portion gives
% an optional stopping threshold. Iteration will cease if the increase in
% log likelihood density per data point is less than this value. Thus l=10.001 will
% stop after 10 iterations or when the increase in log likelihood falls below
% 0.001.
% As a special case, if L=0, then the first three outputs are omitted.
% Use [] to take default value of 100.0001
% M0(k,p) Initial mixture means, one row per mixture.
% V0(k,p) Initial mixture variances, one row per mixture.
% or V0(p,p,k) one full-covariance matrix per mixture
% W0(k,1) Initial mixture weights, one per mixture. The weights should sum to unity.
%
% Alternatively, if initial values for M0, V0 and W0 are not given explicitly:
%
% M0 Number of mixtures required
% V0 Initialization mode:
% 'f' Initialize with K randomly selected data points [default]
% 'p' Initialize with centroids and variances of random partitions
% 'k' k-means algorithm ('kf' and 'kp' determine initialization of kmeans)
% 'h' k-harmonic means algorithm ('hf' and 'hp' determine initialization of kmeans)
% 's' do not scale data during initialization to have equal variances
% 'm' M0 contains the initial centres
% 'v' full covariance matrices
% Mode 'hf' [the default] generally gives the best results but 'f' is faster and often OK
%
% Outputs: (Note that M, V and W are omitted if L==0)
%
% M(k,p) Mixture means, one row per mixture. (omitted if L==0)
% V(k,p) Mixture variances, one row per mixture. (omitted if L==0)
% or V(p,p,k) if full covariance matrices in use (i.e. either 'v' option or V0(p,p,k) specified)
% W(k,1) Mixture weights, one per mixture. The weights will sum to unity. (omitted if L==0)
% G Average log probability of the input data points.
% F Fisher's Discriminant measures how well the data divides into classes.
% It is the ratio of the between-mixture variance to the average mixture variance: a
% high value means the classes (mixtures) are well separated.
% PP(n,1) Log probability of each data point
% GG(l+1,1) Average log probabilities at the beginning of each iteration and at the end
% Bugs/Suggestions
% (2) Allow processing in chunks by outputting/reinputting an array of sufficient statistics
% (6) Other initialization options:
% 'l' LBG algorithm
% 'm' Move-means (dog-rabbit) algorithm
% Copyright (C) Mike Brookes 2000-2009
% Version: $Id: gaussmix.m,v 1.18 2009/04/06 07:40:59 dmb Exp $
%
% VOICEBOX is a MATLAB toolbox for speech processing.
% Home page: http://www.ee.ic.ac.uk/hp/staff/dmb/voicebox/voicebox.html
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 2 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You can obtain a copy of the GNU General Public License from
% http://www.gnu.org/copyleft/gpl.html or by writing to
% Free Software Foundation, Inc.,675 Mass Ave, Cambridge, MA 02139, USA.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[n,p]=size(x);
mx0=sum(x,1)/n; % calculate mean and variance of input data
vx0=sum(x.^2,1)/n-mx0.^2;
sx0=sqrt(vx0);
sx0(sx0==0)=1; % do not divide by zero when scaling
scaled=0; % data is not yet scaled
memsize=voicebox('memsize'); % set memory size to use
if isempty(c)
c=1/n^2;
else
c=c(1); % just to prevent legacy code failing
end
fulliv=0; % initial variance is not full
if isempty(l)
l=100+1e-4; % max loop count + stopping threshold
end
if nargin<6 % no initial values specified for m0, v0, w0
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% No initialvalues given, so we must use k-means or equivalent
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if any(v0=='m')
k=size(m0,1);
else
k=m0;
end
fv=any(v0=='v'); % full covariance matrices requested
if n<=k % each data point can have its own mixture
xs=(x-mx0(ones(n,1),:))./sx0(ones(n,1),:); % scale the data
m=xs(mod((1:k)-1,n)+1,:); % just include all points several times
v=zeros(k,p); % will be set to floor later
w=zeros(k,1);
w(1:n)=1/n;
if l>0
l=0.1; % no point in iterating
end
else % more points than mixtures
if nargin<5
v0='hf'; % default initialization mode: hf
end
if any(v0=='s')
xs=x; % do not scale data during initialization
else
xs=(x-mx0(ones(n,1),:))./sx0(ones(n,1),:); % else scale now
if any(v0=='m')
m=(m0-mx0(ones(k,1),:))./sx0(ones(k,1),:); % scale specified means as well
end
end
w=repmat(1/k,k,1); % all mixtures equally likely
if any(v0=='k') % k-means initialization
if any(v0=='m')
[m,e,j]=kmeans(xs,k,m);
elseif any(v0=='p')
[m,e,j]=kmeans(xs,k,'p');
else
[m,e,j]=kmeans(xs,k,'f');
end
elseif any(v0=='h') % k-harmonic means initialization
if any(v0=='m')
[m,e,j]=kmeanhar(xs,k,[],4,m);
else
if any(v0=='p')
[m,e,j]=kmeanhar(xs,k,[],4,'p');
else
[m,e,j]=kmeanhar(xs,k,[],4,'f');
end
end
elseif any(v0=='p') % Initialize using a random partition
j=ceil(rand(n,1)*k); % allocate to random clusters
j(rnsubset(k,n))=1:k; % but force at least one point per cluster
for i=1:k
m(i,:)=mean(xs(j==i,:),1);
end
else
if any(v0=='m')
m=m0; % use specified centres
else
m=xs(rnsubset(k,n),:); % Forgy initialization: sample k centres without replacement [default]
end
[e,j]=kmeans(xs,k,m,0); % find out the cluster allocation
end
if any(v0=='s')
xs=(x-mx0(ones(n,1),:))./sx0(ones(n,1),:); % scale data now if not done previously
end
v=zeros(k,p); % diagonal covariances
w=zeros(k,1);
for i=1:k
ni=sum(j==i); % number assigned to this centre
w(i)=(ni+1)/(n+k); % weight of this mixture
if ni
v(i,:)=sum((xs(j==i,:)-repmat(m(i,:),ni,1)).^2,1)/ni;
else
v(i,:)=zeros(1,p);
end
end
end
else
%%%%%%%%%%%%%%%%%%%%%%%%
% use initial values given as input parameters
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[k,p]=size(m0);
xs=(x-mx0(ones(n,1),:))./sx0(ones(n,1),:); % scale the data
m=(m0-mx0(ones(k,1),:))./sx0(ones(k,1),:); % and the means
v=v0;
w=w0;
fv=ndims(v)>2 || size(v,1)>k; % full covariance matrix is supplied
if fv
mk=eye(p)==0; % off-diagonal elements
fulliv=any(v(repmat(mk,[1 1 k]))~=0); % check if any are non-zero
if ~fulliv
v=reshape(v(repmat(~mk,[1 1 k])),p,k)'./repmat(sx0.^2,k,1); % just pick out and scale the diagonal elements for now
else
v=v./repmat(sx0'*sx0,[1 1 k]); % scale the full covariance matrix
end
end
end
lsx=sum(log(sx0));
if ~fulliv % initializing with diagonal covariance
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Diagonal Covariance matrices %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
v=max(v,c); % apply the lower bound
xs2=xs.^2; % square the data for variance calculations
% If data size is large then do calculations in chunks
nb=min(n,max(1,floor(memsize/(8*p*k)))); % chunk size for testing data points
nl=ceil(n/nb); % number of chunks
jx0=n-(nl-1)*nb; % size of first chunk
im=repmat(1:k,1,nb); im=im(:);
th=(l-floor(l))*n;
sd=(nargout > 3*(l~=0)); % = 1 if we are outputting log likelihood values
l=floor(l)+sd; % extra loop needed to calculate final G value
lpx=zeros(1,n); % log probability of each data point
wk=ones(k,1);
wp=ones(1,p);
wnb=ones(1,nb);
wnj=ones(1,jx0);
% EM loop
g=0; % dummy initial value for comparison
gg=zeros(l+1,1);
ss=sd; % initialize stopping count (0 or 1)
for j=1:l
g1=g; % save previous log likelihood (2*pi factor omitted)
m1=m; % save previous means, variances and weights
v1=v;
w1=w;
vi=-0.5*v.^(-1); % data-independent scale factor in exponent
lvm=log(w)-0.5*sum(log(v),2); % log of external scale factor (excluding -0.5*p*log(2pi) term)
% first do partial chunk
jx=jx0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -