| Description of slfmm |
slfmm
PURPOSE 
SLFMM Learns a Finite Mixture Model (FMM)
SYNOPSIS 
function [S, cw, pp, info] = slfmm(X, n, estfunctor, evalfunctor, varargin)
DESCRIPTION 
CROSS-REFERENCE INFORMATION 
This function calls:
This function is called by:
- slgmm SLGMM Learns Gaussian Mixture model from samples
SUBFUNCTIONS 
- function models = fmm_em_est(models, data, Q, props)
- function Q = fmm_em_eval(models, data, Q, props)
- function isconverged = fmm_em_cmp(models_prev, models, Q_prev, Q, props)
- function [S, cw] = init_models(X, W, props)
- function [pp, W] = update_weightmap(S, cw, X, n, props)
- function [S, W, cw] = update_models(S, X, W, selinds, props)
- function is_weak = select_weak_components(cw, thres)
- function [S, W, cw] = anneal_components(S, W, cw, props)
- function [S, W, cw] = update_compweights(S, W, props)
- function [pp, W] = labels2weights(labels, sweights)
- function W = weightmap(pp, weights)
- function checkvalid(name, val, range)
SOURCE CODE 
0001 function [S, cw, pp, info] = slfmm(X, n, estfunctor, evalfunctor, varargin)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125 props.method = 'EM';
0126 props.update = 'pass';
0127 props.cyclecn = 1;
0128 props.iter = {'maxiter', 100};
0129 props.tol = 1e-6;
0130 props.verbose = true;
0131 props.initc = [];
0132 props.initpp = [];
0133 props.annthres = 0;
0134 props.weights = [];
0135 props.estmode = 'simple';
0136 props.condpmode = 'normal';
0137 props.manifunc = [];
0138
0139 props = slparseprops(props, varargin{:});
0140
0141
0142 props.estfunctor = estfunctor;
0143 props.evalfunctor = evalfunctor;
0144
0145
0146 checkvalid('learning method', props.method, {'EM'});
0147 checkvalid('updating scheme', props.update, {'pass', 'comp'});
0148 checkvalid('estimation mode', props.estmode, {'simple', 'innermul'});
0149 checkvalid('conditional probability form', props.condpmode, {'normal', 'log'});
0150
0151 if isempty(props.initc) && isempty(props.initpp)
0152 error('sltoolbox:invalidarg', ...
0153 'Please specify either initc or initpp');
0154 end
0155
0156 if ~isempty(props.weights)
0157 if ~isequal(size(props.weights), [1, n])
0158 error('sltoolbox:sizmismatch', ...
0159 'The weights should be a 1 x n row vector');
0160 end
0161 end
0162
0163 if props.annthres > 0
0164 if isempty(props.manifunc)
0165 error('sltoolbox:rterror', ...
0166 'The manipulation function is required when component annealing is on');
0167 end
0168 end
0169
0170
0171
0172
0173 slsharedisp_attach('slfmm', 'show', props.verbose);
0174
0175
0176 if ~isempty(props.initpp)
0177
0178 pp = props.initpp;
0179 W = weightmap(pp, props.weights);
0180
0181 elseif ~isempty(props.initc)
0182
0183 [pp, W] = labels2weights(props.initc, props.weights);
0184
0185 end
0186
0187 initK = size(W, 1);
0188
0189 slsharedisp('FMM Learning Parameters:');
0190 slsharedisp_incindent;
0191 slsharedisp('method = %s', props.method);
0192 slsharedisp('update = %s', props.update);
0193 slsharedisp('estmode = %s', props.estmode);
0194 slsharedisp('init K = %d', initK);
0195 slsharedisp('anneal thres = %g', props.annthres);
0196 slsharedisp_decindent;
0197
0198
0199
0200 switch props.method
0201 case 'EM'
0202 slsharedisp('Run Finite-Mixture Model Learning by EM');
0203
0204 em_estfunctor = {@fmm_em_est, props};
0205 em_evalfunctor = {@fmm_em_eval, props};
0206 em_cmpfunctor = {@fmm_em_cmp, props};
0207
0208 models = {[], []};
0209 data = {X, n};
0210 Q = {pp, W};
0211
0212 props.iter = {props.iter{:}, 'titlebreak', false};
0213 [models, Q, info] = slreevallearn(models, Q, data, ...
0214 em_estfunctor, em_evalfunctor, em_cmpfunctor, ...
0215 'iter', props.iter, 'isrecorded', false);
0216
0217 S = models{1};
0218 cw = models{2};
0219 pp = Q{1};
0220
0221 end
0222
0223 slsharedisp_detach;
0224
0225
0226
0227
0228
0229
0230
0231
0232 function models = fmm_em_est(models, data, Q, props)
0233
0234 S = models{1};
0235 X = data{1};
0236
0237 W = Q{2};
0238
0239 if isempty(S)
0240 [S, cw] = init_models(X, W, props);
0241
0242 else
0243 switch props.update
0244 case 'pass'
0245 [S, W, cw] = update_models(S, X, W, [], props);
0246 slignorevars(W);
0247
0248 case 'comp'
0249 cn = max(ceil(props.cyclecn * size(W, 1)), 1);
0250 for t = 1 : cn
0251 si = ceil(rand * size(W,1));
0252 si = min(max(si, 1), size(W, 1));
0253 [S, W, cw] = update_models(S, X, W, si, props);
0254 end
0255 end
0256 end
0257
0258 models = {S, cw};
0259
0260
0261 function Q = fmm_em_eval(models, data, Q, props)
0262
0263 S = models{1}; cw = models{2};
0264 X = data{1}; n = data{2};
0265 slignorevars(Q);
0266
0267 [pp, W] = update_weightmap(S, cw, X, n, props);
0268
0269 Q = {pp, W};
0270
0271
0272 function isconverged = fmm_em_cmp(models_prev, models, Q_prev, Q, props)
0273
0274 slignorevars(models_prev, models);
0275
0276 W_prev = Q_prev{2};
0277 W = Q{2};
0278 isconverged = false;
0279
0280 slsharedisp_attach('fmm_em_cmp');
0281
0282 if isequal(size(W), size(W_prev))
0283 wdiff = sldiscrep(W_prev, W, 'maxdiffnrm', true);
0284 slsharedisp('K = %d: wdiff = %g', size(W, 1), wdiff);
0285 if wdiff < props.tol
0286 isconverged = true;
0287 end
0288 else
0289 slsharedisp('K = %d -> %d', size(W_prev, 1), size(W, 1));
0290 end
0291
0292 slsharedisp_detach;
0293
0294
0295
0296
0297
0298
0299
0300 function [S, cw] = init_models(X, W, props)
0301
0302 [k, n] = size(W);
0303 switch props.estmode
0304 case 'simple'
0305 for i = 1 : k
0306 S(i,1) = slevalfunctor(props.estfunctor, [], X, n, W(i, :));
0307 end
0308 case 'innermul'
0309 S = slevalfunctor(props.estfunctor, [], X, n, W, []);
0310 end
0311
0312 cw = sum(W, 2);
0313 cw = cw / sum(cw);
0314
0315
0316
0317 function [pp, W] = update_weightmap(S, cw, X, n, props)
0318
0319
0320 k = length(cw);
0321 switch props.estmode
0322 case 'simple'
0323 condp = zeros(k, n);
0324 for i = 1 : k
0325 condp(i, :) = slevalfunctor(props.evalfunctor, S(i), X, n);
0326 end
0327 case 'innermul'
0328 condp = slevalfunctor(props.evalfunctor, S, X, n);
0329 end
0330
0331
0332 switch props.condpmode
0333 case 'normal'
0334 pp = slposteriori(condp, cw);
0335 case 'log'
0336 pp = slposteriori(condp, cw, 'log');
0337 end
0338
0339
0340 W = weightmap(pp, props.weights);
0341
0342
0343
0344 function [S, W, cw] = update_models(S, X, W, selinds, props)
0345
0346
0347 k0 = size(W, 1);
0348 [S, W, cw] = update_compweights(S, W, props);
0349 k1 = size(W, 1);
0350 if k0 ~= k1
0351 return;
0352 end
0353
0354
0355 [k, n] = size(W);
0356 switch props.estmode
0357 case 'simple'
0358 if isempty(selinds)
0359 for i = 1 : k
0360 S(i,1) = slevalfunctor(props.estfunctor, S(i), X, n, W(i,:));
0361 end
0362 else
0363 ns = length(selinds);
0364 for ii = 1 : ns
0365 i = selinds(ii);
0366 S(i,1) = slevalfunctor(props.estfunctor, S(i), X, n, W(i,:));
0367 end
0368 end
0369 case 'innermul'
0370 S = slevalfunctor(props.estfunctor, S, X, n, W, selinds);
0371 end
0372
0373
0374
0375
0376
0377
0378
0379
0380 function is_weak = select_weak_components(cw, thres)
0381
0382 wthres = thres / length(cw);
0383 is_weak = (cw < wthres);
0384
0385
0386
0387 function [S, W, cw] = anneal_components(S, W, cw, props)
0388
0389 is_weak = select_weak_components(cw, props.annthres);
0390 if all(is_weak)
0391 [maxw, si] = max(cw);
0392 slignorevars(maxw);
0393 elseif any(is_weak)
0394 si = find(~is_weak);
0395 else
0396 return;
0397 end
0398
0399 switch props.estmode
0400 case 'simple'
0401 S = S(si);
0402 case 'innermul'
0403 S = feval(props.manifunc, S, 'select', si);
0404 end
0405
0406 W = W(si, :);
0407
0408 cw = cw(si);
0409 cw = cw / sum(cw);
0410
0411
0412
0413 function [S, W, cw] = update_compweights(S, W, props)
0414
0415 cw = sum(W, 2);
0416 cw = cw / sum(cw);
0417
0418 if props.annthres > 0
0419 [S, W, cw] = anneal_components(S, W, cw, props);
0420 end
0421
0422
0423
0424 function [pp, W] = labels2weights(labels, sweights)
0425
0426 labelset = unique(labels);
0427 [tf, inds] = ismember(labels, labelset);
0428 slignorevars(tf);
0429 clear tf;
0430 k = length(labelset);
0431 n = length(labels);
0432
0433 pp = zeros(k, n);
0434 pp(((1:n) - 1) * k + inds) = 1;
0435 W = weightmap(pp, sweights);
0436
0437
0438
0439
0440 function W = weightmap(pp, weights)
0441
0442 if isempty(weights)
0443 W = pp;
0444 else
0445 W = slmulvec(pp, weights, 2);
0446 end
0447
0448
0449
0450
0451 function checkvalid(name, val, range)
0452
0453 if ~ismember(val, range)
0454 error('sltoolbox:invalidarg', ...
0455 'Invalid %s: %s', name, val);
0456 end
0457
0458
0459
Generated on Wed 20-Sep-2006 12:43:11 by m2html © 2003
|
|