-
-
Notifications
You must be signed in to change notification settings - Fork 23
/
ToolGmm.m
104 lines (81 loc) · 2.84 KB
/
ToolGmm.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
%gaussian mixture model
%>
%> @param FeatureMatrix: features for all train observations (dimension iNumFeatures x iNumObservations)
%> @param k: number of gaussians
%> @param numMaxIter: maximum number of iterations (stop if not converged before)
%> @param prevState: internal state that can be stored to continue clustering later
%>
%> @retval mu means
%> @retval sigma standard deviations
%> @retval state result containing internal state (if needed)
% ======================================================================
function [mu, sigma, state] = ToolGmm(V, k, numMaxIter, prevState)
if (nargin < 3)
numMaxIter = 1000;
end
if (nargin == 4)
state = prevState;
else
% initialize state
state = initState_I(V, k);
end
for j = 1:numMaxIter
prevState = state;
% compute weighted gaussian
p = computeProb_I(V, state);
% update clusters
state = updateGaussians_I(V, p, state);
% if we have converged, break
if (max(sum(abs(state.m-prevState.m))) <= 1e-20)
break;
end
end
mu = state.m;
sigma = state.sigma;
end
function [state] = updateGaussians_I(FeatureMatrix, p, state)
% number of clusters
K = size(state.m, 2);
% update priors
state.prior = mean(p, 1)';
for k = 1:K
s = 0;
% update means
state.m(:, k) = FeatureMatrix * p(:, k) / sum(p(:, k));
% subtract mean
F = FeatureMatrix - repmat(state.m(:, k), 1, size(FeatureMatrix, 2));
for n = 1:size(FeatureMatrix, 2)
s = s + p(n, k) * (F(:, n) * F(:, n)');
end
state.sigma(:, :, k) = s / sum(p(:, k));
end
end
function [p] = computeProb_I(FeatureMatrix, state)
K = size(state.m, 2);
p = zeros(size(FeatureMatrix, 2), K);
% for each cluster
for k = 1:K
% subtract mean
F = FeatureMatrix - repmat(state.m(:, k), 1, size(FeatureMatrix, 2));
% weighted gaussian
p(:, k) = 1 / sqrt((2*pi)^size(F, 1) * det(state.sigma(:, :, k))) *...
exp(-1/2 * sum((F .* (inv(state.sigma(:, :, k)) * F)), 1)');
p(:, k) = state.prior(k) * p(:, k);
end
% norm over clusters
p = p ./ repmat(sum(p, 2), 1, K);
end
function [state] = initState_I(FeatureMatrix, K)
%init
m = zeros(size(FeatureMatrix, 1), K);
sigma = zeros(size(FeatureMatrix, 1), size(FeatureMatrix, 1), K);
prior = zeros(1, K);
% pick random points as cluster means
mIdx = round(rand(1, K) * (size(FeatureMatrix, 2)-1)) + 1;
% assign means etc.
m = FeatureMatrix(:, mIdx);
prior = ones(1, K) / K;
sigma = repmat(cov(FeatureMatrix'), 1, 1, K);
% write initial state
state = struct('m', m, 'sigma', sigma, 'prior', prior);
end