| wolffd@0 | 1 %DEMGMM3 Demonstrate density modelling with a Gaussian mixture model. | 
| wolffd@0 | 2 % | 
| wolffd@0 | 3 %	Description | 
| wolffd@0 | 4 %	 The problem consists of modelling data generated by a mixture of | 
| wolffd@0 | 5 %	three Gaussians in 2 dimensions with a mixture model using diagonal | 
| wolffd@0 | 6 %	covariance matrices.  The priors are 0.3, 0.5 and 0.2; the centres | 
| wolffd@0 | 7 %	are (2, 3.5), (0, 0) and (0,2); the covariances are all axis aligned | 
| wolffd@0 | 8 %	(0.16, 0.64), (0.25, 1) and the identity matrix. The first figure | 
| wolffd@0 | 9 %	contains a scatter plot of the data. | 
| wolffd@0 | 10 % | 
| wolffd@0 | 11 %	A Gaussian mixture model with three components is trained using EM. | 
| wolffd@0 | 12 %	The parameter vector is printed before training and after training. | 
| wolffd@0 | 13 %	The user should press any key to continue at these points.  The | 
| wolffd@0 | 14 %	parameter vector consists of priors (the column), and centres (given | 
| wolffd@0 | 15 %	as (x, y) pairs as the next two columns).  The diagonal entries of | 
| wolffd@0 | 16 %	the covariance matrices are printed separately. | 
| wolffd@0 | 17 % | 
| wolffd@0 | 18 %	The second figure is a 3 dimensional view of the density function, | 
| wolffd@0 | 19 %	while the third shows the axes of the 1-standard deviation circles | 
| wolffd@0 | 20 %	for the three components of the mixture model. | 
| wolffd@0 | 21 % | 
| wolffd@0 | 22 %	See also | 
| wolffd@0 | 23 %	GMM, GMMINIT, GMMEM, GMMPROB, GMMUNPAK | 
| wolffd@0 | 24 % | 
| wolffd@0 | 25 | 
| wolffd@0 | 26 %	Copyright (c) Ian T Nabney (1996-2001) | 
| wolffd@0 | 27 | 
| wolffd@0 | 28 % Generate the data | 
| wolffd@0 | 29 ndata = 500; | 
| wolffd@0 | 30 | 
| wolffd@0 | 31 % Fix the seeds for reproducible results | 
| wolffd@0 | 32 randn('state', 42); | 
| wolffd@0 | 33 rand('state', 42); | 
| wolffd@0 | 34 data = randn(ndata, 2); | 
| wolffd@0 | 35 prior = [0.3 0.5 0.2]; | 
| wolffd@0 | 36 % Mixture model swaps clusters 1 and 3 | 
| wolffd@0 | 37 datap = [0.2 0.5 0.3]; | 
| wolffd@0 | 38 datac = [0 2; 0 0; 2 3.5]; | 
| wolffd@0 | 39 datacov = [1 1;1 0.25; 0.4*0.4 0.8*0.8]; | 
| wolffd@0 | 40 data1 = data(1:prior(1)*ndata,:); | 
| wolffd@0 | 41 data2 = data(prior(1)*ndata+1:(prior(2)+prior(1))*ndata, :); | 
| wolffd@0 | 42 data3 = data((prior(1)+prior(2))*ndata +1:ndata, :); | 
| wolffd@0 | 43 | 
| wolffd@0 | 44 % First cluster has axis aligned variance and centre (2, 3.5) | 
| wolffd@0 | 45 data1(:, 1) = data1(:, 1)*0.4 + 2.0; | 
| wolffd@0 | 46 data1(:, 2) = data1(:, 2)*0.8 + 3.5; | 
| wolffd@0 | 47 | 
| wolffd@0 | 48 % Second cluster has axis aligned variance and centre (0, 0) | 
| wolffd@0 | 49 data2(:,2) = data2(:, 2)*0.5; | 
| wolffd@0 | 50 | 
| wolffd@0 | 51 % Third cluster is at (0,2) with identity matrix for covariance | 
| wolffd@0 | 52 data3 = data3 + repmat([0 2], prior(3)*ndata, 1); | 
| wolffd@0 | 53 | 
| wolffd@0 | 54 % Put the dataset together again | 
| wolffd@0 | 55 data = [data1; data2; data3]; | 
| wolffd@0 | 56 | 
| wolffd@0 | 57 clc | 
| wolffd@0 | 58 disp('This demonstration illustrates the use of a Gaussian mixture model') | 
| wolffd@0 | 59 disp('with diagonal covariance matrices to approximate the unconditional') | 
| wolffd@0 | 60 disp('probability density of data in a two-dimensional space.') | 
| wolffd@0 | 61 disp('We begin by generating the data from a mixture of three Gaussians') | 
| wolffd@0 | 62 disp('with axis aligned covariance structure and plotting it.') | 
| wolffd@0 | 63 disp(' ') | 
| wolffd@0 | 64 disp('The first cluster has centre (0, 2).') | 
| wolffd@0 | 65 disp('The second cluster has centre (0, 0).') | 
| wolffd@0 | 66 disp('The third cluster has centre (2, 3.5).') | 
| wolffd@0 | 67 disp(' ') | 
| wolffd@0 | 68 disp('Press any key to continue') | 
| wolffd@0 | 69 pause | 
| wolffd@0 | 70 | 
| wolffd@0 | 71 fh1 = figure; | 
| wolffd@0 | 72 plot(data(:, 1), data(:, 2), 'o') | 
| wolffd@0 | 73 set(gca, 'Box', 'on') | 
| wolffd@0 | 74 | 
| wolffd@0 | 75 % Set up mixture model | 
| wolffd@0 | 76 ncentres = 3; | 
| wolffd@0 | 77 input_dim = 2; | 
| wolffd@0 | 78 mix = gmm(input_dim, ncentres, 'diag'); | 
| wolffd@0 | 79 | 
| wolffd@0 | 80 options = foptions; | 
| wolffd@0 | 81 options(14) = 5;	% Just use 5 iterations of k-means in initialisation | 
| wolffd@0 | 82 % Initialise the model parameters from the data | 
| wolffd@0 | 83 mix = gmminit(mix, data, options); | 
| wolffd@0 | 84 | 
| wolffd@0 | 85 % Print out model | 
| wolffd@0 | 86 disp('The mixture model has three components and diagonal covariance') | 
| wolffd@0 | 87 disp('matrices.  The model parameters after initialisation using the') | 
| wolffd@0 | 88 disp('k-means algorithm are as follows') | 
| wolffd@0 | 89 disp('    Priors        Centres') | 
| wolffd@0 | 90 disp([mix.priors' mix.centres]) | 
| wolffd@0 | 91 disp('Covariance diagonals are') | 
| wolffd@0 | 92 disp(mix.covars) | 
| wolffd@0 | 93 disp('Press any key to continue.') | 
| wolffd@0 | 94 pause | 
| wolffd@0 | 95 | 
| wolffd@0 | 96 % Set up vector of options for EM trainer | 
| wolffd@0 | 97 options = zeros(1, 18); | 
| wolffd@0 | 98 options(1)  = 1;		% Prints out error values. | 
| wolffd@0 | 99 options(14) = 20;		% Number of iterations. | 
| wolffd@0 | 100 | 
| wolffd@0 | 101 disp('We now train the model using the EM algorithm for 20 iterations.') | 
| wolffd@0 | 102 disp(' ') | 
| wolffd@0 | 103 disp('Press any key to continue.') | 
| wolffd@0 | 104 pause | 
| wolffd@0 | 105 | 
| wolffd@0 | 106 [mix, options, errlog] = gmmem(mix, data, options); | 
| wolffd@0 | 107 | 
| wolffd@0 | 108 % Print out model | 
| wolffd@0 | 109 disp(' ') | 
| wolffd@0 | 110 disp('The trained model has priors and centres:') | 
| wolffd@0 | 111 disp('    Priors        Centres') | 
| wolffd@0 | 112 disp([mix.priors' mix.centres]) | 
| wolffd@0 | 113 disp('The data generator has priors and centres') | 
| wolffd@0 | 114 disp('    Priors        Centres') | 
| wolffd@0 | 115 disp([datap' datac]) | 
| wolffd@0 | 116 disp('Model covariance diagonals are') | 
| wolffd@0 | 117 disp(mix.covars) | 
| wolffd@0 | 118 disp('Data generator covariance diagonals are') | 
| wolffd@0 | 119 disp(datacov) | 
| wolffd@0 | 120 disp('Note the close correspondence between these parameters and those') | 
| wolffd@0 | 121 disp('of the distribution used to generate the data.') | 
| wolffd@0 | 122 disp(' ') | 
| wolffd@0 | 123 disp('Press any key to continue.') | 
| wolffd@0 | 124 pause | 
| wolffd@0 | 125 | 
| wolffd@0 | 126 clc | 
| wolffd@0 | 127 disp('We now plot the density given by the mixture model as a surface plot.') | 
| wolffd@0 | 128 disp(' ') | 
| wolffd@0 | 129 disp('Press any key to continue.') | 
| wolffd@0 | 130 pause | 
| wolffd@0 | 131 | 
| wolffd@0 | 132 % Plot the result | 
| wolffd@0 | 133 x = -4.0:0.2:5.0; | 
| wolffd@0 | 134 y = -4.0:0.2:5.0; | 
| wolffd@0 | 135 [X, Y] = meshgrid(x,y); | 
| wolffd@0 | 136 X = X(:); | 
| wolffd@0 | 137 Y = Y(:); | 
| wolffd@0 | 138 grid = [X Y]; | 
| wolffd@0 | 139 Z = gmmprob(mix, grid); | 
| wolffd@0 | 140 Z = reshape(Z, length(x), length(y)); | 
| wolffd@0 | 141 c = mesh(x, y, Z); | 
| wolffd@0 | 142 hold on | 
| wolffd@0 | 143 title('Surface plot of probability density') | 
| wolffd@0 | 144 hold off | 
| wolffd@0 | 145 drawnow | 
| wolffd@0 | 146 | 
| wolffd@0 | 147 clc | 
| wolffd@0 | 148 disp('The final plot shows the centres and widths, given by one standard') | 
| wolffd@0 | 149 disp('deviation, of the three components of the mixture model.  The axes') | 
| wolffd@0 | 150 disp('of the ellipses of constant density are shown.') | 
| wolffd@0 | 151 disp(' ') | 
| wolffd@0 | 152 disp('Press any key to continue.') | 
| wolffd@0 | 153 pause | 
| wolffd@0 | 154 | 
| wolffd@0 | 155 % Try to calculate a sensible position for the second figure, below the first | 
| wolffd@0 | 156 fig1_pos = get(fh1, 'Position'); | 
| wolffd@0 | 157 fig2_pos = fig1_pos; | 
| wolffd@0 | 158 fig2_pos(2) = fig2_pos(2) - fig1_pos(4); | 
| wolffd@0 | 159 fh2 = figure('Position', fig2_pos); | 
| wolffd@0 | 160 | 
| wolffd@0 | 161 h = plot(data(:, 1), data(:, 2), 'bo'); | 
| wolffd@0 | 162 hold on | 
| wolffd@0 | 163 axis('equal'); | 
| wolffd@0 | 164 title('Plot of data and covariances') | 
| wolffd@0 | 165 for i = 1:ncentres | 
| wolffd@0 | 166   v = [1 0]; | 
| wolffd@0 | 167   for j = 1:2 | 
| wolffd@0 | 168     start=mix.centres(i,:)-sqrt(mix.covars(i,:).*v); | 
| wolffd@0 | 169     endpt=mix.centres(i,:)+sqrt(mix.covars(i,:).*v); | 
| wolffd@0 | 170     linex = [start(1) endpt(1)]; | 
| wolffd@0 | 171     liney = [start(2) endpt(2)]; | 
| wolffd@0 | 172     line(linex, liney, 'Color', 'k', 'LineWidth', 3) | 
| wolffd@0 | 173     v = [0 1]; | 
| wolffd@0 | 174   end | 
| wolffd@0 | 175   % Plot ellipses of one standard deviation | 
| wolffd@0 | 176   theta = 0:0.02:2*pi; | 
| wolffd@0 | 177   x = sqrt(mix.covars(i,1))*cos(theta) + mix.centres(i,1); | 
| wolffd@0 | 178   y = sqrt(mix.covars(i,2))*sin(theta) + mix.centres(i,2); | 
| wolffd@0 | 179   plot(x, y, 'r-'); | 
| wolffd@0 | 180 end | 
| wolffd@0 | 181 hold off | 
| wolffd@0 | 182 | 
| wolffd@0 | 183 disp('Note how the data cluster positions and widths are captured by') | 
| wolffd@0 | 184 disp('the mixture model.') | 
| wolffd@0 | 185 disp(' ') | 
| wolffd@0 | 186 disp('Press any key to end.') | 
| wolffd@0 | 187 pause | 
| wolffd@0 | 188 | 
| wolffd@0 | 189 close(fh1); | 
| wolffd@0 | 190 close(fh2); | 
| wolffd@0 | 191 clear all; | 
| wolffd@0 | 192 |