annotate toolboxes/MIRtoolbox1.3.2/somtoolbox/som_train_struct.m @ 0:cc4b1211e677 tip

initial commit to HG from Changeset: 646 (e263d8a21543) added further path and more save "camirversion.m"
author Daniel Wolff
date Fri, 19 Aug 2016 13:07:06 +0200
parents
children
rev   line source
Daniel@0 1 function sTrain = som_train_struct(varargin)
Daniel@0 2
Daniel@0 3 %SOM_TRAIN_STRUCT Default values for SOM training parameters.
Daniel@0 4 %
Daniel@0 5 % sT = som_train_struct([[argID,] value, ...])
Daniel@0 6 %
Daniel@0 7 % sTrain = som_train_struct('train',sM,sD);
Daniel@0 8 % sTrain = som_train_struct('finetune','data',D);
Daniel@0 9 % sTrain = som_train_struct('previous',sT0);
Daniel@0 10 %
Daniel@0 11 % Input and output arguments ([]'s are optional):
Daniel@0 12 % [argID, (string) Several default values depend on other SOM parameters
Daniel@0 13 % value] (varies) or on the proporties of a data set. See below for a
Daniel@0 14 % a list of required and optional arguments for
Daniel@0 15 % different parameters, and well as the list of valid
Daniel@0 16 % argIDs and associated values. The values which are
Daniel@0 17 % unambiguous can be given without the preceeding argID.
Daniel@0 18 %
Daniel@0 19 % sT (struct) The training struct.
Daniel@0 20 %
Daniel@0 21 % Training struct contains values for training and initialization
Daniel@0 22 % parameters. These parameters depend on the number of training samples,
Daniel@0 23 % phase of training, the training algorithm.
Daniel@0 24 %
Daniel@0 25 % Here are the valid argument IDs and corresponding values. The values which
Daniel@0 26 % are unambiguous (marked with '*') can be given without the preceeding rgID.
Daniel@0 27 % 'dim' (scalar) input space dimension
Daniel@0 28 % 'dlen' (scalar) length of the training data
Daniel@0 29 % 'data' (matrix / struct) the training data
Daniel@0 30 % 'munits' (scalar) number of map units
Daniel@0 31 % 'msize' (vector) map size
Daniel@0 32 % 'previous' (struct) previous training struct can be given in
Daniel@0 33 % conjunction with 'finetune' phase (see below)
Daniel@0 34 % 'phase' *(string) training phase: 'init', 'train', 'rough' or 'finetune'
Daniel@0 35 % 'algorithm' *(string) algorithm to use: 'lininit', 'randinit', 'batch' or 'seq'
Daniel@0 36 % 'map' *(struct) If a map struct is given, the last training struct
Daniel@0 37 % in '.trainhist' field is used as the previous training
Daniel@0 38 % struct. The map size and input space dimension are
Daniel@0 39 % extracted from the map struct.
Daniel@0 40 % 'sTrain' *(struct) a train struct, the empty fields of which are
Daniel@0 41 % filled with sensible values
Daniel@0 42 %
Daniel@0 43 % For more help, try 'type som_train_struct' or check out online documentation.
Daniel@0 44 % See also SOM_SET, SOM_TOPOL_STRUCT, SOM_MAKE.
Daniel@0 45
Daniel@0 46 %%%%%%%%%%%%% DETAILED DESCRIPTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Daniel@0 47 %
Daniel@0 48 % som_train_struct
Daniel@0 49 %
Daniel@0 50 % PURPOSE
Daniel@0 51 %
Daniel@0 52 % Default values for SOM training parameters.
Daniel@0 53 %
Daniel@0 54 % SYNTAX
Daniel@0 55 %
Daniel@0 56 % sT = som_train_struct('argID',value,...);
Daniel@0 57 % sT = som_train_struct(value,...);
Daniel@0 58 %
Daniel@0 59 % DESCRIPTION
Daniel@0 60 %
Daniel@0 61 % This function is used to give sensible values for SOM training
Daniel@0 62 % parameters and returns a training struct. Often, the parameters
Daniel@0 63 % depend on the properties of the map and the training data. These are
Daniel@0 64 % given as optional arguments to the function. If a partially filled
Daniel@0 65 % train struct is given, its empty fields (field value is [] or '' or
Daniel@0 66 % NaN) are supplimented with default values.
Daniel@0 67 %
Daniel@0 68 % The training struct has a number of fields which depend on each other
Daniel@0 69 % and the optional arguments in complex ways. The most important argument
Daniel@0 70 % is 'phase' which can be either 'init', 'train', 'rough' or 'finetune'.
Daniel@0 71 %
Daniel@0 72 % 'init' Map initialization.
Daniel@0 73 % 'train' Map training in a onepass operation, as opposed to the
Daniel@0 74 % rough-finetune combination.
Daniel@0 75 % 'rough' Rough organization of the map: large neighborhood, big
Daniel@0 76 % initial value for learning coefficient. Short training.
Daniel@0 77 % 'finetune' Finetuning the map after rough organization phase. Small
Daniel@0 78 % neighborhood, learning coefficient is small already at
Daniel@0 79 % the beginning. Long training.
Daniel@0 80 %
Daniel@0 81 % The fields of training struct set by this function are listed below.
Daniel@0 82 %
Daniel@0 83 % '.mask' Basically, a column vector of ones. But if a previous
Daniel@0 84 % train or map struct is given, it is copied from there.
Daniel@0 85 % '.neigh' Default value is 'gaussian' but if a previous train or map
Daniel@0 86 % struct is given, it is copied from there.
Daniel@0 87 % '.alpha_type' Default value is 'inv' but if a previous training struct
Daniel@0 88 % is given, it is copied from there.
Daniel@0 89 % '.alpha_ini' For 'train' and 'rough' phases, this is 0.5, for
Daniel@0 90 % 'finetune' it is 0.05.
Daniel@0 91 % '.radius_ini' Depends on the previous training operation and the
Daniel@0 92 % maximum sidelength of the map ms = max(msize).
Daniel@0 93 % if there isn't one, or it is 'randinit', rad_ini = max(1,ms/2)
Daniel@0 94 % if it is 'lininit', rad_ini = max(1,ms/8)
Daniel@0 95 % otherwise, rad_ini = rad_fin of the previous training
Daniel@0 96 % '.radius_fin' Default value is 1, but if the training phase is
Daniel@0 97 % 'rough', rad_fin = max(1,rad_ini/4).
Daniel@0 98 % '.trainlen' For 'train' phase this is 20 x mpd epochs, for 'rough'
Daniel@0 99 % phase 4 x mpd epochs and for 'finetune' 16 x mpd
Daniel@0 100 % epochs, where mpd = munits/dlen. If mpd cannot be
Daniel@0 101 % calculated, it is set to be = 0.5. In any case,
Daniel@0 102 % trainlen is at least one epoch.
Daniel@0 103 % '.algorithm' Default training algorithm is 'batch' and default
Daniel@0 104 % initialization algorithm is 'lininit'.
Daniel@0 105 %
Daniel@0 106 % OPTIONAL INPUT ARGUMENTS
Daniel@0 107 %
Daniel@0 108 % argID (string) Argument identifier string (see below).
Daniel@0 109 % value (varies) Value for the argument (see below).
Daniel@0 110 %
Daniel@0 111 % The optional arguments can be given as 'argID',value -pairs. If an
Daniel@0 112 % argument is given value multiple times, the last one is used. The
Daniel@0 113 % valid IDs and corresponding values are listed below. The values
Daniel@0 114 % which are unambiguous (marked with '*') can be given without the
Daniel@0 115 % preceeding argID.
Daniel@0 116 %
Daniel@0 117 % 'dim' (scalar) input space dimension
Daniel@0 118 % 'dlen' (scalar) length of the training data
Daniel@0 119 % 'data' (matrix / struct) the training data
Daniel@0 120 % 'munits' (scalar) number of map units
Daniel@0 121 % 'msize' (vector) map size
Daniel@0 122 % 'previous' (struct) previous training struct can be given in
Daniel@0 123 % conjunction with 'finetune' phase.
Daniel@0 124 % 'phase' *(string) training phase: 'init', 'train', 'rough' or 'finetune'
Daniel@0 125 % 'algorithm' *(string) algorithm to use: 'lininit', 'randinit',
Daniel@0 126 % 'batch' or 'seq'
Daniel@0 127 % 'map' *(struct) If a map struc is given, the last training struct
Daniel@0 128 % in '.trainhist' field is used as the previous training
Daniel@0 129 % struct. The map size and input space dimension are
Daniel@0 130 % extracted from the map struct.
Daniel@0 131 % 'sTrain' *(struct) a train struct, the empty fields of which are
Daniel@0 132 % filled with sensible values
Daniel@0 133 %
Daniel@0 134 % OUTPUT ARGUMENTS
Daniel@0 135 %
Daniel@0 136 % sT (struct) The training struct.
Daniel@0 137 %
Daniel@0 138 % EXAMPLES
Daniel@0 139 %
Daniel@0 140 % The most important optional argument for the training parameters is
Daniel@0 141 % 'phase'. The second most important are 'previous' and/or 'map'.
Daniel@0 142 %
Daniel@0 143 % To get default initialization parameters, use:
Daniel@0 144 %
Daniel@0 145 % sTrain = som_train_struct('phase','init');
Daniel@0 146 % or
Daniel@0 147 % sTrain = som_train_struct('init');
Daniel@0 148 %
Daniel@0 149 % To get default training parameters, use:
Daniel@0 150 %
Daniel@0 151 % sTrain = som_train_struct('phase','train','data',D,'map',sMap);
Daniel@0 152 % or
Daniel@0 153 % sTrain = som_train_struct('train','data',D,sMap);
Daniel@0 154 % or
Daniel@0 155 % sTrain = som_train_struct('train','dlen',dlen, ...
Daniel@0 156 % 'msize',sMap.topol.msize,'dim',dim);
Daniel@0 157 %
Daniel@0 158 % If you want to first rough train and then finetune, do like this:
Daniel@0 159 %
Daniel@0 160 % sT1 = som_train_struct('rough','dlen',length(D),sMap); % rough training
Daniel@0 161 % sT2 = som_train_struct('finetune','previous',sT1); % finetuning
Daniel@0 162 %
Daniel@0 163 % SEE ALSO
Daniel@0 164 %
Daniel@0 165 % som_make Initialize and train a map using default parameters.
Daniel@0 166 % som_topol_struct Default map topology.
Daniel@0 167 % som_randinint Random initialization algorithm.
Daniel@0 168 % som_lininit Linear initialization algorithm.
Daniel@0 169 % som_seqtrain Sequential training algorithm.
Daniel@0 170 % som_batchtrain Batch training algorithm.
Daniel@0 171
Daniel@0 172 % Copyright (c) 1999-2000 by the SOM toolbox programming team.
Daniel@0 173 % http://www.cis.hut.fi/projects/somtoolbox/
Daniel@0 174
Daniel@0 175 % Version 2.0beta juuso 101199 090200 210301
Daniel@0 176
Daniel@0 177 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Daniel@0 178 %% check arguments
Daniel@0 179
Daniel@0 180 % initial default structs
Daniel@0 181 sTrain = som_set('som_train');
Daniel@0 182
Daniel@0 183 % initialize optional parameters
Daniel@0 184 dlen = NaN;
Daniel@0 185 msize = 0;
Daniel@0 186 munits = NaN;
Daniel@0 187 sTprev = [];
Daniel@0 188 dim = NaN;
Daniel@0 189 phase = '';
Daniel@0 190
Daniel@0 191 % varargin
Daniel@0 192 i=1;
Daniel@0 193 while i<=length(varargin),
Daniel@0 194 argok = 1;
Daniel@0 195 if ischar(varargin{i}),
Daniel@0 196 switch varargin{i},
Daniel@0 197 case 'dim', i=i+1; dim = varargin{i};
Daniel@0 198 case 'dlen', i=i+1; dlen = varargin{i};
Daniel@0 199 case 'msize', i=i+1; msize = varargin{i};
Daniel@0 200 case 'munits', i=i+1; munits = varargin{i}; msize = 0;
Daniel@0 201 case 'phase', i=i+1; phase = varargin{i};
Daniel@0 202 case 'algorithm', i=i+1; sTrain.algorithm = varargin{i};
Daniel@0 203 case 'mask', i=i+1; sTrain.mask = varargin{i};
Daniel@0 204 case {'previous','map'},
Daniel@0 205 i=i+1;
Daniel@0 206 if strcmp(varargin{i}.type,'som_map'),
Daniel@0 207 if length(varargin{i}.trainhist),
Daniel@0 208 sTprev = varargin{i}.trainhist(end);
Daniel@0 209 msize = varargin{i}.topol.msize;
Daniel@0 210 end
Daniel@0 211 elseif strcmp(varargin{i}.type,'som_train'),
Daniel@0 212 sTprev = varargin{i};
Daniel@0 213 end
Daniel@0 214 case 'data',
Daniel@0 215 i=i+1;
Daniel@0 216 if isstruct(varargin{i}), [dlen dim] = size(varargin{i}.data);
Daniel@0 217 else [dlen dim] = size(varargin{i});
Daniel@0 218 end
Daniel@0 219 case {'init','train','rough','finetune'}, phase = varargin{i};
Daniel@0 220 case {'lininit','randinit','seq','batch'}, sTrain.algorithm = varargin{i};
Daniel@0 221 otherwise argok=0;
Daniel@0 222 end
Daniel@0 223 elseif isstruct(varargin{i}) & isfield(varargin{i},'type'),
Daniel@0 224 switch varargin{i}.type,
Daniel@0 225 case 'som_train',
Daniel@0 226 sT = varargin{i};
Daniel@0 227 if ~isempty(sT.algorithm), sTrain.algorithm = sT.algorithm; end
Daniel@0 228 if ~isempty(sT.neigh), sTrain.neigh = sT.neigh; end
Daniel@0 229 if ~isempty(sT.mask), sTrain.mask = sT.mask; end
Daniel@0 230 if ~isnan(sT.radius_ini), sTrain.radius_ini = sT.radius_ini; end
Daniel@0 231 if ~isnan(sT.radius_fin), sTrain.radius_fin = sT.radius_fin; end
Daniel@0 232 if ~isnan(sT.alpha_ini), sTrain.alpha_ini = sT.alpha_ini; end
Daniel@0 233 if ~isempty(sT.alpha_type), sTrain.alpha_type = sT.alpha_type; end
Daniel@0 234 if ~isnan(sT.trainlen), sTrain.trainlen = sT.trainlen; end
Daniel@0 235 if ~isempty(sT.data_name), sTrain.data_name = sT.data_name; end
Daniel@0 236 if ~isempty(sT.time), sTrain.time = sT.time; end
Daniel@0 237 case 'som_map',
Daniel@0 238 if strcmp(varargin{i}.type,'som_map'),
Daniel@0 239 if length(varargin{i}.trainhist),
Daniel@0 240 sTprev = varargin{i}.trainhist(end);
Daniel@0 241 msize = varargin{i}.topol.msize;
Daniel@0 242 end
Daniel@0 243 if ~isempty(varargin{i}.neigh) & isempty(sTrain.neigh),
Daniel@0 244 sTrain.neigh = varargin{i}.neigh;
Daniel@0 245 end
Daniel@0 246 if ~isempty(varargin{i}.mask) & isempty(sTrain.mask),
Daniel@0 247 sTrain.mask = varargin{i}.mask;
Daniel@0 248 end
Daniel@0 249 elseif strcmp(varargin{i}.type,'som_train'),
Daniel@0 250 sTprev = varargin{i};
Daniel@0 251 end
Daniel@0 252 case 'som_topol', msize = varargin{i}.msize;
Daniel@0 253 case 'som_data', [dlen dim] = size(varargin{i}.data);
Daniel@0 254 otherwise argok=0;
Daniel@0 255 end
Daniel@0 256 else
Daniel@0 257 argok = 0;
Daniel@0 258 end
Daniel@0 259 if ~argok,
Daniel@0 260 disp(['(som_train_struct) Ignoring invalid argument #' num2str(i)]);
Daniel@0 261 end
Daniel@0 262 i = i+1;
Daniel@0 263 end
Daniel@0 264
Daniel@0 265 % dim
Daniel@0 266 if ~isempty(sTprev) & isnan(dim), dim = length(sTprev.mask); end
Daniel@0 267
Daniel@0 268 % mask
Daniel@0 269 if isempty(sTrain.mask) & ~isnan(dim), sTrain.mask = ones(dim,1); end
Daniel@0 270
Daniel@0 271 % msize, munits
Daniel@0 272 if ~msize | isempty(msize),
Daniel@0 273 if isnan(munits), msize = [10 10];
Daniel@0 274 else s = round(sqrt(munits)); msize = [s round(munits/s)];
Daniel@0 275 end
Daniel@0 276 end
Daniel@0 277 munits = prod(msize);
Daniel@0 278
Daniel@0 279 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Daniel@0 280 %% action
Daniel@0 281
Daniel@0 282 % previous training
Daniel@0 283 prevalg = '';
Daniel@0 284 if ~isempty(sTprev),
Daniel@0 285 if any(findstr(sTprev.algorithm,'init')), prevalg = 'init';
Daniel@0 286 else prevalg = sTprev.algorithm;
Daniel@0 287 end
Daniel@0 288 end
Daniel@0 289
Daniel@0 290 % first determine phase
Daniel@0 291 if isempty(phase),
Daniel@0 292 switch sTrain.algorithm,
Daniel@0 293 case {'lininit','randinit'}, phase = 'init';
Daniel@0 294 case {'batch','seq',''},
Daniel@0 295 if isempty(sTprev), phase = 'rough';
Daniel@0 296 elseif strcmp(prevalg,'init'), phase = 'rough';
Daniel@0 297 else phase = 'finetune';
Daniel@0 298 end
Daniel@0 299 otherwise, phase = 'train';
Daniel@0 300 end
Daniel@0 301 end
Daniel@0 302
Daniel@0 303 % then determine algorithm
Daniel@0 304 if isempty(sTrain.algorithm),
Daniel@0 305 if strcmp(phase,'init'), sTrain.algorithm = 'lininit';
Daniel@0 306 elseif any(strcmp(prevalg,{'init',''})), sTrain.algorithm = 'batch';
Daniel@0 307 else sTrain.algorithm = sTprev.algorithm;
Daniel@0 308 end
Daniel@0 309 end
Daniel@0 310
Daniel@0 311 % mask
Daniel@0 312 if isempty(sTrain.mask),
Daniel@0 313 if ~isempty(sTprev), sTrain.mask = sTprev.mask;
Daniel@0 314 elseif ~isnan(dim), sTrain.mask = ones(dim,1);
Daniel@0 315 end
Daniel@0 316 end
Daniel@0 317
Daniel@0 318 % neighborhood function
Daniel@0 319 if isempty(sTrain.neigh),
Daniel@0 320 if ~isempty(sTprev) & ~isempty(sTprev.neigh), sTrain.neigh = sTprev.neigh;
Daniel@0 321 else sTrain.neigh = 'gaussian';
Daniel@0 322 end
Daniel@0 323 end
Daniel@0 324
Daniel@0 325 if strcmp(phase,'init'),
Daniel@0 326 sTrain.alpha_ini = NaN;
Daniel@0 327 sTrain.alpha_type = '';
Daniel@0 328 sTrain.radius_ini = NaN;
Daniel@0 329 sTrain.radius_fin = NaN;
Daniel@0 330 sTrain.trainlen = NaN;
Daniel@0 331 sTrain.neigh = '';
Daniel@0 332 else
Daniel@0 333 mode = [phase, '-', sTrain.algorithm];
Daniel@0 334
Daniel@0 335 % learning rate
Daniel@0 336 if isnan(sTrain.alpha_ini),
Daniel@0 337 if strcmp(sTrain.algorithm,'batch'), sTrain.alpha_ini = NaN;
Daniel@0 338 else
Daniel@0 339 switch phase,
Daniel@0 340 case {'train','rough'}, sTrain.alpha_ini = 0.5;
Daniel@0 341 case 'finetune', sTrain.alpha_ini = 0.05;
Daniel@0 342 end
Daniel@0 343 end
Daniel@0 344 end
Daniel@0 345 if isempty(sTrain.alpha_type),
Daniel@0 346 if ~isempty(sTprev) & ~isempty(sTprev.alpha_type) ...
Daniel@0 347 & ~strcmp(sTrain.algorithm,'batch'),
Daniel@0 348 sTrain.alpha_type = sTprev.alpha_type;
Daniel@0 349 elseif strcmp(sTrain.algorithm,'seq'),
Daniel@0 350 sTrain.alpha_type = 'inv';
Daniel@0 351 end
Daniel@0 352 end
Daniel@0 353
Daniel@0 354 % radius
Daniel@0 355 ms = max(msize);
Daniel@0 356 if isnan(sTrain.radius_ini),
Daniel@0 357 if isempty(sTprev) | strcmp(sTprev.algorithm,'randinit'),
Daniel@0 358 sTrain.radius_ini = max(1,ceil(ms/4));
Daniel@0 359 elseif strcmp(sTprev.algorithm,'lininit') | isnan(sTprev.radius_fin),
Daniel@0 360 sTrain.radius_ini = max(1,ceil(ms/8));
Daniel@0 361 else
Daniel@0 362 sTrain.radius_ini = sTprev.radius_fin;
Daniel@0 363 end
Daniel@0 364 end
Daniel@0 365 if isnan(sTrain.radius_fin),
Daniel@0 366 if strcmp(phase,'rough'),
Daniel@0 367 sTrain.radius_fin = max(1,sTrain.radius_ini/4);
Daniel@0 368 else
Daniel@0 369 sTrain.radius_fin = 1;
Daniel@0 370 end
Daniel@0 371 end
Daniel@0 372
Daniel@0 373 % trainlen
Daniel@0 374 if isnan(sTrain.trainlen),
Daniel@0 375 mpd = munits/dlen;
Daniel@0 376 if isnan(mpd), mpd = 0.5; end
Daniel@0 377 switch phase,
Daniel@0 378 case 'train', sTrain.trainlen = ceil(50*mpd);
Daniel@0 379 case 'rough', sTrain.trainlen = ceil(10*mpd);
Daniel@0 380 case 'finetune', sTrain.trainlen = ceil(40*mpd);
Daniel@0 381 end
Daniel@0 382 sTrain.trainlen = max(1,sTrain.trainlen);
Daniel@0 383 end
Daniel@0 384
Daniel@0 385 end
Daniel@0 386
Daniel@0 387 return;
Daniel@0 388
Daniel@0 389 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%