annotate toolboxes/MIRtoolbox1.3.2/somtoolbox/som_seqtrain.m @ 0:e9a9cd732c1e tip

first hg version after svn
author wolffd
date Tue, 10 Feb 2015 15:05:51 +0000
parents
children
rev   line source
wolffd@0 1 function [sMap, sTrain] = som_seqtrain(sMap, D, varargin)
wolffd@0 2
wolffd@0 3 %SOM_SEQTRAIN Use sequential algorithm to train the Self-Organizing Map.
wolffd@0 4 %
wolffd@0 5 % [sM,sT] = som_seqtrain(sM, D, [[argID,] value, ...])
wolffd@0 6 %
wolffd@0 7 % sM = som_seqtrain(sM,D);
wolffd@0 8 % sM = som_seqtrain(sM,sD,'alpha_type','power','tracking',3);
wolffd@0 9 % [M,sT] = som_seqtrain(M,D,'ep','trainlen',10,'inv','hexa');
wolffd@0 10 %
wolffd@0 11 % Input and output arguments ([]'s are optional):
wolffd@0 12 % sM (struct) map struct, the trained and updated map is returned
wolffd@0 13 % (matrix) codebook matrix of a self-organizing map
wolffd@0 14 % size munits x dim or msize(1) x ... x msize(k) x dim
wolffd@0 15 % The trained map codebook is returned.
wolffd@0 16 % D (struct) training data; data struct
wolffd@0 17 % (matrix) training data, size dlen x dim
wolffd@0 18 % [argID, (string) See below. The values which are unambiguous can
wolffd@0 19 % value] (varies) be given without the preceeding argID.
wolffd@0 20 %
wolffd@0 21 % sT (struct) learning parameters used during the training
wolffd@0 22 %
wolffd@0 23 % Here are the valid argument IDs and corresponding values. The values which
wolffd@0 24 % are unambiguous (marked with '*') can be given without the preceeding argID.
wolffd@0 25 % 'mask' (vector) BMU search mask, size dim x 1
wolffd@0 26 % 'msize' (vector) map size
wolffd@0 27 % 'radius' (vector) neighborhood radiuses, length 1, 2 or trainlen
wolffd@0 28 % 'radius_ini' (scalar) initial training radius
wolffd@0 29 % 'radius_fin' (scalar) final training radius
wolffd@0 30 % 'alpha' (vector) learning rates, length trainlen
wolffd@0 31 % 'alpha_ini' (scalar) initial learning rate
wolffd@0 32 % 'tracking' (scalar) tracking level, 0-3
wolffd@0 33 % 'trainlen' (scalar) training length
wolffd@0 34 % 'trainlen_type' *(string) is the given trainlen 'samples' or 'epochs'
wolffd@0 35 % 'train' *(struct) train struct, parameters for training
wolffd@0 36 % 'sTrain','som_train ' = 'train'
wolffd@0 37 % 'alpha_type' *(string) learning rate function, 'inv', 'linear' or 'power'
wolffd@0 38 % 'sample_order'*(string) order of samples: 'random' or 'ordered'
wolffd@0 39 % 'neigh' *(string) neighborhood function, 'gaussian', 'cutgauss',
wolffd@0 40 % 'ep' or 'bubble'
wolffd@0 41 % 'topol' *(struct) topology struct
wolffd@0 42 % 'som_topol','sTopo l' = 'topol'
wolffd@0 43 % 'lattice' *(string) map lattice, 'hexa' or 'rect'
wolffd@0 44 % 'shape' *(string) map shape, 'sheet', 'cyl' or 'toroid'
wolffd@0 45 %
wolffd@0 46 % For more help, try 'type som_seqtrain' or check out online documentation.
wolffd@0 47 % See also SOM_MAKE, SOM_BATCHTRAIN, SOM_TRAIN_STRUCT.
wolffd@0 48
wolffd@0 49 %%%%%%%%%%%%% DETAILED DESCRIPTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
wolffd@0 50 %
wolffd@0 51 % som_seqtrain
wolffd@0 52 %
wolffd@0 53 % PURPOSE
wolffd@0 54 %
wolffd@0 55 % Trains a Self-Organizing Map using the sequential algorithm.
wolffd@0 56 %
wolffd@0 57 % SYNTAX
wolffd@0 58 %
wolffd@0 59 % sM = som_seqtrain(sM,D);
wolffd@0 60 % sM = som_seqtrain(sM,sD);
wolffd@0 61 % sM = som_seqtrain(...,'argID',value,...);
wolffd@0 62 % sM = som_seqtrain(...,value,...);
wolffd@0 63 % [sM,sT] = som_seqtrain(M,D,...);
wolffd@0 64 %
wolffd@0 65 % DESCRIPTION
wolffd@0 66 %
wolffd@0 67 % Trains the given SOM (sM or M above) with the given training data
wolffd@0 68 % (sD or D) using sequential SOM training algorithm. If no optional
wolffd@0 69 % arguments (argID, value) are given, a default training is done, the
wolffd@0 70 % parameters are obtained from SOM_TRAIN_STRUCT function. Using
wolffd@0 71 % optional arguments the training parameters can be specified. Returns
wolffd@0 72 % the trained and updated SOM and a train struct which contains
wolffd@0 73 % information on the training.
wolffd@0 74 %
wolffd@0 75 % REFERENCES
wolffd@0 76 %
wolffd@0 77 % Kohonen, T., "Self-Organizing Map", 2nd ed., Springer-Verlag,
wolffd@0 78 % Berlin, 1995, pp. 78-82.
wolffd@0 79 % Kohonen, T., "Clustering, Taxonomy, and Topological Maps of
wolffd@0 80 % Patterns", International Conference on Pattern Recognition
wolffd@0 81 % (ICPR), 1982, pp. 114-128.
wolffd@0 82 % Kohonen, T., "Self-Organized formation of topologically correct
wolffd@0 83 % feature maps", Biological Cybernetics 43, 1982, pp. 59-69.
wolffd@0 84 %
wolffd@0 85 % REQUIRED INPUT ARGUMENTS
wolffd@0 86 %
wolffd@0 87 % sM The map to be trained.
wolffd@0 88 % (struct) map struct
wolffd@0 89 % (matrix) codebook matrix (field .data of map struct)
wolffd@0 90 % Size is either [munits dim], in which case the map grid
wolffd@0 91 % dimensions (msize) should be specified with optional arguments,
wolffd@0 92 % or [msize(1) ... msize(k) dim] in which case the map
wolffd@0 93 % grid dimensions are taken from the size of the matrix.
wolffd@0 94 % Lattice, by default, is 'rect' and shape 'sheet'.
wolffd@0 95 % D Training data.
wolffd@0 96 % (struct) data struct
wolffd@0 97 % (matrix) data matrix, size [dlen dim]
wolffd@0 98 %
wolffd@0 99 % OPTIONAL INPUT ARGUMENTS
wolffd@0 100 %
wolffd@0 101 % argID (string) Argument identifier string (see below).
wolffd@0 102 % value (varies) Value for the argument (see below).
wolffd@0 103 %
wolffd@0 104 % The optional arguments can be given as 'argID',value -pairs. If an
wolffd@0 105 % argument is given value multiple times, the last one is
wolffd@0 106 % used. The valid IDs and corresponding values are listed below. The values
wolffd@0 107 % which are unambiguous (marked with '*') can be given without the
wolffd@0 108 % preceeding argID.
wolffd@0 109 %
wolffd@0 110 % 'mask' (vector) BMU search mask, size dim x 1. Default is
wolffd@0 111 % the one in sM (field '.mask') or a vector of
wolffd@0 112 % ones if only a codebook matrix was given.
wolffd@0 113 % 'msize' (vector) map grid dimensions. Default is the one
wolffd@0 114 % in sM (field sM.topol.msize) or
wolffd@0 115 % 'si = size(sM); msize = si(1:end-1);'
wolffd@0 116 % if only a codebook matrix was given.
wolffd@0 117 % 'radius' (vector) neighborhood radius
wolffd@0 118 % length = 1: radius_ini = radius
wolffd@0 119 % length = 2: [radius_ini radius_fin] = radius
wolffd@0 120 % length > 2: the vector given neighborhood
wolffd@0 121 % radius for each step separately
wolffd@0 122 % trainlen = length(radius)
wolffd@0 123 % 'radius_ini' (scalar) initial training radius
wolffd@0 124 % 'radius_fin' (scalar) final training radius
wolffd@0 125 % 'alpha' (vector) learning rate
wolffd@0 126 % length = 1: alpha_ini = alpha
wolffd@0 127 % length > 1: the vector gives learning rate
wolffd@0 128 % for each step separately
wolffd@0 129 % trainlen is set to length(alpha)
wolffd@0 130 % alpha_type is set to 'user defined'
wolffd@0 131 % 'alpha_ini' (scalar) initial learning rate
wolffd@0 132 % 'tracking' (scalar) tracking level: 0, 1 (default), 2 or 3
wolffd@0 133 % 0 - estimate time
wolffd@0 134 % 1 - track time and quantization error
wolffd@0 135 % 2 - plot quantization error
wolffd@0 136 % 3 - plot quantization error and two first
wolffd@0 137 % components
wolffd@0 138 % 'trainlen' (scalar) training length (see also 'tlen_type')
wolffd@0 139 % 'trainlen_type' *(string) is the trainlen argument given in 'epochs'
wolffd@0 140 % or in 'samples'. Default is 'epochs'.
wolffd@0 141 % 'sample_order'*(string) is the sample order 'random' (which is the
wolffd@0 142 % the default) or 'ordered' in which case
wolffd@0 143 % samples are taken in the order in which they
wolffd@0 144 % appear in the data set
wolffd@0 145 % 'train' *(struct) train struct, parameters for training.
wolffd@0 146 % Default parameters, unless specified,
wolffd@0 147 % are acquired using SOM_TRAIN_STRUCT (this
wolffd@0 148 % also applies for 'trainlen', 'alpha_type',
wolffd@0 149 % 'alpha_ini', 'radius_ini' and 'radius_fin').
wolffd@0 150 % 'sTrain', 'som_train' (struct) = 'train'
wolffd@0 151 % 'neigh' *(string) The used neighborhood function. Default is
wolffd@0 152 % the one in sM (field '.neigh') or 'gaussian'
wolffd@0 153 % if only a codebook matrix was given. Other
wolffd@0 154 % possible values is 'cutgauss', 'ep' and 'bubble'.
wolffd@0 155 % 'topol' *(struct) topology of the map. Default is the one
wolffd@0 156 % in sM (field '.topol').
wolffd@0 157 % 'sTopol', 'som_topol' (struct) = 'topol'
wolffd@0 158 % 'alpha_type'*(string) learning rate function, 'inv', 'linear' or 'power'
wolffd@0 159 % 'lattice' *(string) map lattice. Default is the one in sM
wolffd@0 160 % (field sM.topol.lattice) or 'rect'
wolffd@0 161 % if only a codebook matrix was given.
wolffd@0 162 % 'shape' *(string) map shape. Default is the one in sM
wolffd@0 163 % (field sM.topol.shape) or 'sheet'
wolffd@0 164 % if only a codebook matrix was given.
wolffd@0 165 %
wolffd@0 166 % OUTPUT ARGUMENTS
wolffd@0 167 %
wolffd@0 168 % sM the trained map
wolffd@0 169 % (struct) if a map struct was given as input argument, a
wolffd@0 170 % map struct is also returned. The current training
wolffd@0 171 % is added to the training history (sM.trainhist).
wolffd@0 172 % The 'neigh' and 'mask' fields of the map struct
wolffd@0 173 % are updated to match those of the training.
wolffd@0 174 % (matrix) if a matrix was given as input argument, a matrix
wolffd@0 175 % is also returned with the same size as the input
wolffd@0 176 % argument.
wolffd@0 177 % sT (struct) train struct; information of the accomplished training
wolffd@0 178 %
wolffd@0 179 % EXAMPLES
wolffd@0 180 %
wolffd@0 181 % Simplest case:
wolffd@0 182 % sM = som_seqtrain(sM,D);
wolffd@0 183 % sM = som_seqtrain(sM,sD);
wolffd@0 184 %
wolffd@0 185 % To change the tracking level, 'tracking' argument is specified:
wolffd@0 186 % sM = som_seqtrain(sM,D,'tracking',3);
wolffd@0 187 %
wolffd@0 188 % The change training parameters, the optional arguments 'train',
wolffd@0 189 % 'neigh','mask','trainlen','radius','radius_ini', 'radius_fin',
wolffd@0 190 % 'alpha', 'alpha_type' and 'alpha_ini' are used.
wolffd@0 191 % sM = som_seqtrain(sM,D,'neigh','cutgauss','trainlen',10,'radius_fin',0);
wolffd@0 192 %
wolffd@0 193 % Another way to specify training parameters is to create a train struct:
wolffd@0 194 % sTrain = som_train_struct(sM,'dlen',size(D,1),'algorithm','seq');
wolffd@0 195 % sTrain = som_set(sTrain,'neigh','cutgauss');
wolffd@0 196 % sM = som_seqtrain(sM,D,sTrain);
wolffd@0 197 %
wolffd@0 198 % By default the neighborhood radius goes linearly from radius_ini to
wolffd@0 199 % radius_fin. If you want to change this, you can use the 'radius' argument
wolffd@0 200 % to specify the neighborhood radius for each step separately:
wolffd@0 201 % sM = som_seqtrain(sM,D,'radius',[5 3 1 1 1 1 0.5 0.5 0.5]);
wolffd@0 202 %
wolffd@0 203 % By default the learning rate (alpha) goes from the alpha_ini to 0
wolffd@0 204 % along the function defined by alpha_type. If you want to change this,
wolffd@0 205 % you can use the 'alpha' argument to specify the learning rate
wolffd@0 206 % for each step separately:
wolffd@0 207 % alpha = 0.2*(1 - log([1:100]));
wolffd@0 208 % sM = som_seqtrain(sM,D,'alpha',alpha);
wolffd@0 209 %
wolffd@0 210 % You don't necessarily have to use the map struct, but you can operate
wolffd@0 211 % directly with codebook matrices. However, in this case you have to
wolffd@0 212 % specify the topology of the map in the optional arguments. The
wolffd@0 213 % following commads are identical (M is originally a 200 x dim sized matrix):
wolffd@0 214 % M = som_seqtrain(M,D,'msize',[20 10],'lattice','hexa','shape','cyl');
wolffd@0 215 %
wolffd@0 216 % M = som_seqtrain(M,D,'msize',[20 10],'hexa','cyl');
wolffd@0 217 %
wolffd@0 218 % sT= som_set('som_topol','msize',[20 10],'lattice','hexa','shape','cyl');
wolffd@0 219 % M = som_seqtrain(M,D,sT);
wolffd@0 220 %
wolffd@0 221 % M = reshape(M,[20 10 dim]);
wolffd@0 222 % M = som_seqtrain(M,D,'hexa','cyl');
wolffd@0 223 %
wolffd@0 224 % The som_seqtrain also returns a train struct with information on the
wolffd@0 225 % accomplished training. This is the same one as is added to the end of the
wolffd@0 226 % trainhist field of map struct, in case a map struct is given.
wolffd@0 227 % [M,sTrain] = som_seqtrain(M,D,'msize',[20 10]);
wolffd@0 228 %
wolffd@0 229 % [sM,sTrain] = som_seqtrain(sM,D); % sM.trainhist{end}==sTrain
wolffd@0 230 %
wolffd@0 231 % SEE ALSO
wolffd@0 232 %
wolffd@0 233 % som_make Initialize and train a SOM using default parameters.
wolffd@0 234 % som_batchtrain Train SOM with batch algorithm.
wolffd@0 235 % som_train_struct Determine default training parameters.
wolffd@0 236
wolffd@0 237 % Copyright (c) 1997-2000 by the SOM toolbox programming team.
wolffd@0 238 % http://www.cis.hut.fi/projects/somtoolbox/
wolffd@0 239
wolffd@0 240 % Version 1.0beta juuso 220997
wolffd@0 241 % Version 2.0beta juuso 101199
wolffd@0 242
wolffd@0 243 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
wolffd@0 244 %% Check arguments
wolffd@0 245
wolffd@0 246 error(nargchk(2, Inf, nargin)); % check the number of input arguments
wolffd@0 247
wolffd@0 248 % map
wolffd@0 249 struct_mode = isstruct(sMap);
wolffd@0 250 if struct_mode,
wolffd@0 251 sTopol = sMap.topol;
wolffd@0 252 else
wolffd@0 253 orig_size = size(sMap);
wolffd@0 254 if ndims(sMap) > 2,
wolffd@0 255 si = size(sMap); dim = si(end); msize = si(1:end-1);
wolffd@0 256 M = reshape(sMap,[prod(msize) dim]);
wolffd@0 257 else
wolffd@0 258 msize = [orig_size(1) 1];
wolffd@0 259 dim = orig_size(2);
wolffd@0 260 end
wolffd@0 261 sMap = som_map_struct(dim,'msize',msize);
wolffd@0 262 sTopol = sMap.topol;
wolffd@0 263 end
wolffd@0 264 [munits dim] = size(sMap.codebook);
wolffd@0 265
wolffd@0 266 % data
wolffd@0 267 if isstruct(D),
wolffd@0 268 data_name = D.name;
wolffd@0 269 D = D.data;
wolffd@0 270 else
wolffd@0 271 data_name = inputname(2);
wolffd@0 272 end
wolffd@0 273 D = D(find(sum(isnan(D),2) < dim),:); % remove empty vectors from the data
wolffd@0 274 [dlen ddim] = size(D); % check input dimension
wolffd@0 275 if dim ~= ddim, error('Map and data input space dimensions disagree.'); end
wolffd@0 276
wolffd@0 277 % varargin
wolffd@0 278 sTrain = som_set('som_train','algorithm','seq','neigh', ...
wolffd@0 279 sMap.neigh,'mask',sMap.mask,'data_name',data_name);
wolffd@0 280 radius = [];
wolffd@0 281 alpha = [];
wolffd@0 282 tracking = 1;
wolffd@0 283 sample_order_type = 'random';
wolffd@0 284 tlen_type = 'epochs';
wolffd@0 285
wolffd@0 286 i=1;
wolffd@0 287 while i<=length(varargin),
wolffd@0 288 argok = 1;
wolffd@0 289 if ischar(varargin{i}),
wolffd@0 290 switch varargin{i},
wolffd@0 291 % argument IDs
wolffd@0 292 case 'msize', i=i+1; sTopol.msize = varargin{i};
wolffd@0 293 case 'lattice', i=i+1; sTopol.lattice = varargin{i};
wolffd@0 294 case 'shape', i=i+1; sTopol.shape = varargin{i};
wolffd@0 295 case 'mask', i=i+1; sTrain.mask = varargin{i};
wolffd@0 296 case 'neigh', i=i+1; sTrain.neigh = varargin{i};
wolffd@0 297 case 'trainlen', i=i+1; sTrain.trainlen = varargin{i};
wolffd@0 298 case 'trainlen_type', i=i+1; tlen_type = varargin{i};
wolffd@0 299 case 'tracking', i=i+1; tracking = varargin{i};
wolffd@0 300 case 'sample_order', i=i+1; sample_order_type = varargin{i};
wolffd@0 301 case 'radius_ini', i=i+1; sTrain.radius_ini = varargin{i};
wolffd@0 302 case 'radius_fin', i=i+1; sTrain.radius_fin = varargin{i};
wolffd@0 303 case 'radius',
wolffd@0 304 i=i+1;
wolffd@0 305 l = length(varargin{i});
wolffd@0 306 if l==1,
wolffd@0 307 sTrain.radius_ini = varargin{i};
wolffd@0 308 else
wolffd@0 309 sTrain.radius_ini = varargin{i}(1);
wolffd@0 310 sTrain.radius_fin = varargin{i}(end);
wolffd@0 311 if l>2, radius = varargin{i}; tlen_type = 'samples'; end
wolffd@0 312 end
wolffd@0 313 case 'alpha_type', i=i+1; sTrain.alpha_type = varargin{i};
wolffd@0 314 case 'alpha_ini', i=i+1; sTrain.alpha_ini = varargin{i};
wolffd@0 315 case 'alpha',
wolffd@0 316 i=i+1;
wolffd@0 317 sTrain.alpha_ini = varargin{i}(1);
wolffd@0 318 if length(varargin{i})>1,
wolffd@0 319 alpha = varargin{i}; tlen_type = 'samples';
wolffd@0 320 sTrain.alpha_type = 'user defined';
wolffd@0 321 end
wolffd@0 322 case {'sTrain','train','som_train'}, i=i+1; sTrain = varargin{i};
wolffd@0 323 case {'topol','sTopol','som_topol'},
wolffd@0 324 i=i+1;
wolffd@0 325 sTopol = varargin{i};
wolffd@0 326 if prod(sTopol.msize) ~= munits,
wolffd@0 327 error('Given map grid size does not match the codebook size.');
wolffd@0 328 end
wolffd@0 329 % unambiguous values
wolffd@0 330 case {'inv','linear','power'}, sTrain.alpha_type = varargin{i};
wolffd@0 331 case {'hexa','rect'}, sTopol.lattice = varargin{i};
wolffd@0 332 case {'sheet','cyl','toroid'}, sTopol.shape = varargin{i};
wolffd@0 333 case {'gaussian','cutgauss','ep','bubble'}, sTrain.neigh = varargin{i};
wolffd@0 334 case {'epochs','samples'}, tlen_type = varargin{i};
wolffd@0 335 case {'random', 'ordered'}, sample_order_type = varargin{i};
wolffd@0 336 otherwise argok=0;
wolffd@0 337 end
wolffd@0 338 elseif isstruct(varargin{i}) & isfield(varargin{i},'type'),
wolffd@0 339 switch varargin{i}(1).type,
wolffd@0 340 case 'som_topol',
wolffd@0 341 sTopol = varargin{i};
wolffd@0 342 if prod(sTopol.msize) ~= munits,
wolffd@0 343 error('Given map grid size does not match the codebook size.');
wolffd@0 344 end
wolffd@0 345 case 'som_train', sTrain = varargin{i};
wolffd@0 346 otherwise argok=0;
wolffd@0 347 end
wolffd@0 348 else
wolffd@0 349 argok = 0;
wolffd@0 350 end
wolffd@0 351 if ~argok,
wolffd@0 352 disp(['(som_seqtrain) Ignoring invalid argument #' num2str(i+2)]);
wolffd@0 353 end
wolffd@0 354 i = i+1;
wolffd@0 355 end
wolffd@0 356
wolffd@0 357 % training length
wolffd@0 358 if ~isempty(radius) | ~isempty(alpha),
wolffd@0 359 lr = length(radius);
wolffd@0 360 la = length(alpha);
wolffd@0 361 if lr>2 | la>1,
wolffd@0 362 tlen_type = 'samples';
wolffd@0 363 if lr> 2 & la<=1, sTrain.trainlen = lr;
wolffd@0 364 elseif lr<=2 & la> 1, sTrain.trainlen = la;
wolffd@0 365 elseif lr==la, sTrain.trainlen = la;
wolffd@0 366 else
wolffd@0 367 error('Mismatch between radius and learning rate vector lengths.')
wolffd@0 368 end
wolffd@0 369 end
wolffd@0 370 end
wolffd@0 371 if strcmp(tlen_type,'samples'), sTrain.trainlen = sTrain.trainlen/dlen; end
wolffd@0 372
wolffd@0 373 % check topology
wolffd@0 374 if struct_mode,
wolffd@0 375 if ~strcmp(sTopol.lattice,sMap.topol.lattice) | ...
wolffd@0 376 ~strcmp(sTopol.shape,sMap.topol.shape) | ...
wolffd@0 377 any(sTopol.msize ~= sMap.topol.msize),
wolffd@0 378 warning('Changing the original map topology.');
wolffd@0 379 end
wolffd@0 380 end
wolffd@0 381 sMap.topol = sTopol;
wolffd@0 382
wolffd@0 383 % complement the training struct
wolffd@0 384 sTrain = som_train_struct(sTrain,sMap,'dlen',dlen);
wolffd@0 385 if isempty(sTrain.mask), sTrain.mask = ones(dim,1); end
wolffd@0 386
wolffd@0 387 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
wolffd@0 388 %% initialize
wolffd@0 389
wolffd@0 390 M = sMap.codebook;
wolffd@0 391 mask = sTrain.mask;
wolffd@0 392 trainlen = sTrain.trainlen*dlen;
wolffd@0 393
wolffd@0 394 % neighborhood radius
wolffd@0 395 if length(radius)>2,
wolffd@0 396 radius_type = 'user defined';
wolffd@0 397 else
wolffd@0 398 radius = [sTrain.radius_ini sTrain.radius_fin];
wolffd@0 399 rini = radius(1);
wolffd@0 400 rstep = (radius(end)-radius(1))/(trainlen-1);
wolffd@0 401 radius_type = 'linear';
wolffd@0 402 end
wolffd@0 403
wolffd@0 404 % learning rate
wolffd@0 405 if length(alpha)>1,
wolffd@0 406 sTrain.alpha_type ='user defined';
wolffd@0 407 if length(alpha) ~= trainlen,
wolffd@0 408 error('Trainlen and length of neighborhood radius vector do not match.')
wolffd@0 409 end
wolffd@0 410 if any(isnan(alpha)),
wolffd@0 411 error('NaN is an illegal learning rate.')
wolffd@0 412 end
wolffd@0 413 else
wolffd@0 414 if isempty(alpha), alpha = sTrain.alpha_ini; end
wolffd@0 415 if strcmp(sTrain.alpha_type,'inv'),
wolffd@0 416 % alpha(t) = a / (t+b), where a and b are chosen suitably
wolffd@0 417 % below, they are chosen so that alpha_fin = alpha_ini/100
wolffd@0 418 b = (trainlen - 1) / (100 - 1);
wolffd@0 419 a = b * alpha;
wolffd@0 420 end
wolffd@0 421 end
wolffd@0 422
wolffd@0 423 % initialize random number generator
wolffd@0 424 rand('state',sum(100*clock));
wolffd@0 425
wolffd@0 426 % distance between map units in the output space
wolffd@0 427 % Since in the case of gaussian and ep neighborhood functions, the
wolffd@0 428 % equations utilize squares of the unit distances and in bubble case
wolffd@0 429 % it doesn't matter which is used, the unitdistances and neighborhood
wolffd@0 430 % radiuses are squared.
wolffd@0 431 Ud = som_unit_dists(sTopol).^2;
wolffd@0 432
wolffd@0 433 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
wolffd@0 434 %% Action
wolffd@0 435
wolffd@0 436 update_step = 100;
wolffd@0 437 mu_x_1 = ones(munits,1);
wolffd@0 438 samples = ones(update_step,1);
wolffd@0 439 r = samples;
wolffd@0 440 alfa = samples;
wolffd@0 441
wolffd@0 442 qe = 0;
wolffd@0 443 start = clock;
wolffd@0 444 if tracking > 0, % initialize tracking
wolffd@0 445 track_table = zeros(update_step,1);
wolffd@0 446 qe = zeros(floor(trainlen/update_step),1);
wolffd@0 447 end
wolffd@0 448
wolffd@0 449 for t = 1:trainlen,
wolffd@0 450
wolffd@0 451 % Every update_step, new values for sample indeces, neighborhood
wolffd@0 452 % radius and learning rate are calculated. This could be done
wolffd@0 453 % every step, but this way it is more efficient. Or this could
wolffd@0 454 % be done all at once outside the loop, but it would require much
wolffd@0 455 % more memory.
wolffd@0 456 ind = rem(t,update_step); if ind==0, ind = update_step; end
wolffd@0 457 if ind==1,
wolffd@0 458 steps = [t:min(trainlen,t+update_step-1)];
wolffd@0 459 % sample order
wolffd@0 460 switch sample_order_type,
wolffd@0 461 case 'ordered', samples = rem(steps,dlen)+1;
wolffd@0 462 case 'random', samples = ceil(dlen*rand(update_step,1)+eps);
wolffd@0 463 end
wolffd@0 464
wolffd@0 465 % neighborhood radius
wolffd@0 466 switch radius_type,
wolffd@0 467 case 'linear', r = rini+(steps-1)*rstep;
wolffd@0 468 case 'user defined', r = radius(steps);
wolffd@0 469 end
wolffd@0 470 r=r.^2; % squared radius (see notes about Ud above)
wolffd@0 471 r(r==0) = eps; % zero radius might cause div-by-zero error
wolffd@0 472
wolffd@0 473 % learning rate
wolffd@0 474 switch sTrain.alpha_type,
wolffd@0 475 case 'linear', alfa = (1-steps/trainlen)*alpha;
wolffd@0 476 case 'inv', alfa = a ./ (b + steps-1);
wolffd@0 477 case 'power', alfa = alpha * (0.005/alpha).^((steps-1)/trainlen);
wolffd@0 478 case 'user defined', alfa = alpha(steps);
wolffd@0 479 end
wolffd@0 480 end
wolffd@0 481
wolffd@0 482 % find BMU
wolffd@0 483 x = D(samples(ind),:); % pick one sample vector
wolffd@0 484 known = ~isnan(x); % its known components
wolffd@0 485 Dx = M(:,known) - x(mu_x_1,known); % each map unit minus the vector
wolffd@0 486 [qerr bmu] = min((Dx.^2)*mask(known)); % minimum distance(^2) and the BMU
wolffd@0 487
wolffd@0 488 % tracking
wolffd@0 489 if tracking>0,
wolffd@0 490 track_table(ind) = sqrt(qerr);
wolffd@0 491 if ind==update_step,
wolffd@0 492 n = ceil(t/update_step);
wolffd@0 493 qe(n) = mean(track_table);
wolffd@0 494 trackplot(M,D,tracking,start,n,qe);
wolffd@0 495 end
wolffd@0 496 end
wolffd@0 497
wolffd@0 498 % neighborhood & learning rate
wolffd@0 499 % notice that the elements Ud and radius have been squared!
wolffd@0 500 % (see notes about Ud above)
wolffd@0 501 switch sTrain.neigh,
wolffd@0 502 case 'bubble', h = (Ud(:,bmu)<=r(ind));
wolffd@0 503 case 'gaussian', h = exp(-Ud(:,bmu)/(2*r(ind)));
wolffd@0 504 case 'cutgauss', h = exp(-Ud(:,bmu)/(2*r(ind))) .* (Ud(:,bmu)<=r(ind));
wolffd@0 505 case 'ep', h = (1-Ud(:,bmu)/r(ind)) .* (Ud(:,bmu)<=r(ind));
wolffd@0 506 end
wolffd@0 507 h = h*alfa(ind);
wolffd@0 508
wolffd@0 509 % update M
wolffd@0 510 M(:,known) = M(:,known) - h(:,ones(sum(known),1)).*Dx;
wolffd@0 511
wolffd@0 512 end; % for t = 1:trainlen
wolffd@0 513
wolffd@0 514 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
wolffd@0 515 %% Build / clean up the return arguments
wolffd@0 516
wolffd@0 517 if tracking, fprintf(1,'\n'); end
wolffd@0 518
wolffd@0 519 % update structures
wolffd@0 520 sTrain = som_set(sTrain,'time',datestr(now,0));
wolffd@0 521 if struct_mode,
wolffd@0 522 sMap = som_set(sMap,'codebook',M,'mask',sTrain.mask,'neigh',sTrain.neigh);
wolffd@0 523 tl = length(sMap.trainhist);
wolffd@0 524 sMap.trainhist(tl+1) = sTrain;
wolffd@0 525 else
wolffd@0 526 sMap = reshape(M,orig_size);
wolffd@0 527 end
wolffd@0 528
wolffd@0 529 return;
wolffd@0 530
wolffd@0 531
wolffd@0 532
wolffd@0 533 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
wolffd@0 534 %% subfunctions
wolffd@0 535
wolffd@0 536 %%%%%%%%
wolffd@0 537 function [] = trackplot(M,D,tracking,start,n,qe)
wolffd@0 538
wolffd@0 539 l = length(qe);
wolffd@0 540 elap_t = etime(clock,start);
wolffd@0 541 tot_t = elap_t*l/n;
wolffd@0 542 fprintf(1,'\rTraining: %3.0f/ %3.0f s',elap_t,tot_t)
wolffd@0 543 switch tracking
wolffd@0 544 case 1,
wolffd@0 545 case 2,
wolffd@0 546 plot(1:n,qe(1:n),(n+1):l,qe((n+1):l))
wolffd@0 547 title('Quantization errors for latest samples')
wolffd@0 548 drawnow
wolffd@0 549 otherwise,
wolffd@0 550 subplot(2,1,1), plot(1:n,qe(1:n),(n+1):l,qe((n+1):l))
wolffd@0 551 title('Quantization error for latest samples');
wolffd@0 552 subplot(2,1,2), plot(M(:,1),M(:,2),'ro',D(:,1),D(:,2),'b.');
wolffd@0 553 title('First two components of map units (o) and data vectors (+)');
wolffd@0 554 drawnow
wolffd@0 555 end
wolffd@0 556 % end of trackplot
wolffd@0 557