annotate toolboxes/MIRtoolbox1.3.2/somtoolbox/som_make.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 sMap = som_make(D, varargin)
Daniel@0 2
Daniel@0 3 %SOM_MAKE Create, initialize and train Self-Organizing Map.
Daniel@0 4 %
Daniel@0 5 % sMap = som_make(D, [[argID,] value, ...])
Daniel@0 6 %
Daniel@0 7 % sMap = som_make(D);
Daniel@0 8 % sMap = som_make(D, 'munits', 20);
Daniel@0 9 % sMap = som_make(D, 'munits', 20, 'hexa', 'sheet');
Daniel@0 10 % sMap = som_make(D, 'msize', [4 6 7], 'lattice', 'rect');
Daniel@0 11 %
Daniel@0 12 % Input and output arguments ([]'s are optional):
Daniel@0 13 % D (matrix) training data, size dlen x dim
Daniel@0 14 % (struct) data struct
Daniel@0 15 % [argID, (string) See below. The values which are unambiguous can
Daniel@0 16 % value] (varies) be given without the preceeding argID.
Daniel@0 17 %
Daniel@0 18 % sMap (struct) map struct
Daniel@0 19 %
Daniel@0 20 % Here are the valid argument IDs and corresponding values. The values
Daniel@0 21 % which are unambiguous (marked with '*') can be given without the
Daniel@0 22 % preceeding argID.
Daniel@0 23 % 'init' *(string) initialization: 'randinit' or 'lininit' (default)
Daniel@0 24 % 'algorithm' *(string) training: 'seq' or 'batch' (default) or 'sompak'
Daniel@0 25 % 'munits' (scalar) the preferred number of map units
Daniel@0 26 % 'msize' (vector) map grid size
Daniel@0 27 % 'mapsize' *(string) do you want a 'small', 'normal' or 'big' map
Daniel@0 28 % Any explicit settings of munits or msize override this.
Daniel@0 29 % 'lattice' *(string) map lattice, 'hexa' or 'rect'
Daniel@0 30 % 'shape' *(string) map shape, 'sheet', 'cyl' or 'toroid'
Daniel@0 31 % 'neigh' *(string) neighborhood function, 'gaussian', 'cutgauss',
Daniel@0 32 % 'ep' or 'bubble'
Daniel@0 33 % 'topol' *(struct) topology struct
Daniel@0 34 % 'som_topol','sTopol' = 'topol'
Daniel@0 35 % 'mask' (vector) BMU search mask, size dim x 1
Daniel@0 36 % 'name' (string) map name
Daniel@0 37 % 'comp_names' (string array / cellstr) component names, size dim x 1
Daniel@0 38 % 'tracking' (scalar) how much to report, default = 1
Daniel@0 39 % 'training' (string) 'short', 'default', 'long'
Daniel@0 40 % (vector) size 1 x 2, first length of rough training in epochs,
Daniel@0 41 % and then length of finetuning in epochs
Daniel@0 42 %
Daniel@0 43 % For more help, try 'type som_make' or check out online documentation.
Daniel@0 44 % See also SOM_MAP_STRUCT, SOM_TOPOL_STRUCT, SOM_TRAIN_STRUCT,
Daniel@0 45 % SOM_RANDINIT, SOM_LININIT, SOM_SEQTRAIN, SOM_BATCHTRAIN.
Daniel@0 46
Daniel@0 47 %%%%%%%%%%%%% DETAILED DESCRIPTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Daniel@0 48 %
Daniel@0 49 % som_make
Daniel@0 50 %
Daniel@0 51 % PURPOSE
Daniel@0 52 %
Daniel@0 53 % Creates, initializes and trains a SOM using default parameters.
Daniel@0 54 %
Daniel@0 55 % SYNTAX
Daniel@0 56 %
Daniel@0 57 % sMap = som_make(D);
Daniel@0 58 % sMap = som_make(...,'argID',value,...);
Daniel@0 59 % sMap = som_make(...,value,...);
Daniel@0 60 %
Daniel@0 61 % DESCRIPTION
Daniel@0 62 %
Daniel@0 63 % Creates, initializes and trains a SOM with default parameters. Uses functions
Daniel@0 64 % SOM_TOPOL_STRUCT, SOM_TRAIN_STRUCT, SOM_DATA_STRUCT and SOM_MAP_STRUCT to come
Daniel@0 65 % up with the default values.
Daniel@0 66 %
Daniel@0 67 % First, the number of map units is determined. Unless they are
Daniel@0 68 % explicitly defined, function SOM_TOPOL_STRUCT is used to determine this.
Daniel@0 69 % It uses a heuristic formula of 'munits = 5*dlen^0.54321'. The 'mapsize'
Daniel@0 70 % argument influences the final number of map units: a 'big' map has
Daniel@0 71 % x4 the default number of map units and a 'small' map has x0.25 the
Daniel@0 72 % default number of map units.
Daniel@0 73 %
Daniel@0 74 % After the number of map units has been determined, the map size is
Daniel@0 75 % determined. Basically, the two biggest eigenvalues of the training
Daniel@0 76 % data are calculated and the ratio between sidelengths of the map grid
Daniel@0 77 % is set to this ratio. The actual sidelengths are then set so that
Daniel@0 78 % their product is as close to the desired number of map units as
Daniel@0 79 % possible.
Daniel@0 80 %
Daniel@0 81 % Then the SOM is initialized. First, linear initialization along two
Daniel@0 82 % greatest eigenvectors is tried, but if this can't be done (the
Daniel@0 83 % eigenvectors cannot be calculated), random initialization is used
Daniel@0 84 % instead. After initialization, the SOM is trained in two phases:
Daniel@0 85 % first rough training and then fine-tuning. If the 'tracking'
Daniel@0 86 % argument is greater than zero, the average quantization error and
Daniel@0 87 % topographic error of the final map are calculated.
Daniel@0 88 %
Daniel@0 89 % REQUIRED INPUT ARGUMENTS
Daniel@0 90 %
Daniel@0 91 % D The data to use in the training.
Daniel@0 92 % (struct) A data struct. If a struct is given, '.comp_names' field as
Daniel@0 93 % well as '.comp_norm' field is copied to the map struct.
Daniel@0 94 % (matrix) A data matrix, size dlen x dim. The data matrix may
Daniel@0 95 % contain unknown values, indicated by NaNs.
Daniel@0 96 %
Daniel@0 97 % OPTIONAL INPUT ARGUMENTS
Daniel@0 98 %
Daniel@0 99 % argID (string) Argument identifier string (see below).
Daniel@0 100 % value (varies) Value for the argument (see below).
Daniel@0 101 %
Daniel@0 102 % Here are the valid argument IDs and corresponding values. The values
Daniel@0 103 % which are unambiguous (marked with '*') can be given without the
Daniel@0 104 % preceeding argID.
Daniel@0 105 % 'init' *(string) initialization: 'randinit' or 'lininit' (default)
Daniel@0 106 % 'algorithm' *(string) training: 'seq' or 'batch' (default) or 'sompak'
Daniel@0 107 % 'munits' (scalar) the preferred number of map units
Daniel@0 108 % 'msize' (vector) map grid size
Daniel@0 109 % 'mapsize' *(string) do you want a 'small', 'normal' or 'big' map
Daniel@0 110 % Any explicit settings of munits or msize override this.
Daniel@0 111 % 'lattice' *(string) map lattice, 'hexa' or 'rect'
Daniel@0 112 % 'shape' *(string) map shape, 'sheet', 'cyl' or 'toroid'
Daniel@0 113 % 'neigh' *(string) neighborhood function, 'gaussian', 'cutgauss',
Daniel@0 114 % 'ep' or 'bubble'
Daniel@0 115 % 'topol' *(struct) topology struct
Daniel@0 116 % 'som_topol','sTopol' = 'topol'
Daniel@0 117 % 'mask' (vector) BMU search mask, size dim x 1
Daniel@0 118 % 'name' (string) map name
Daniel@0 119 % 'comp_names' (string array / cellstr) component names, size dim x 1
Daniel@0 120 % 'tracking' (scalar) how much to report, default = 1
Daniel@0 121 % 'training' (string) 'short', 'default' or 'long'
Daniel@0 122 % (vector) size 1 x 2, first length of rough training in epochs,
Daniel@0 123 % and then length of finetuning in epochs
Daniel@0 124 %
Daniel@0 125 % OUTPUT ARGUMENTS
Daniel@0 126 %
Daniel@0 127 % sMap (struct) the trained map struct
Daniel@0 128 %
Daniel@0 129 % EXAMPLES
Daniel@0 130 %
Daniel@0 131 % To simply train a map with default parameters:
Daniel@0 132 %
Daniel@0 133 % sMap = som_make(D);
Daniel@0 134 %
Daniel@0 135 % With the optional arguments, the initialization and training can be
Daniel@0 136 % influenced. To change map size, use 'msize', 'munits' or 'mapsize'
Daniel@0 137 % arguments:
Daniel@0 138 %
Daniel@0 139 % sMap = som_make(D,'mapsize','big'); or sMap=som_make(D,'big');
Daniel@0 140 % sMap = som_make(D,'munits', 100);
Daniel@0 141 % sMap = som_make(D,'msize', [20 10]);
Daniel@0 142 %
Daniel@0 143 % Argument 'algorithm' can be used to switch between 'seq' and 'batch'
Daniel@0 144 % algorithms. 'batch' is the default, so to use 'seq' algorithm:
Daniel@0 145 %
Daniel@0 146 % sMap = som_make(D,'algorithm','seq'); or sMap = som_make(D,'seq');
Daniel@0 147 %
Daniel@0 148 % The 'tracking' argument can be used to control the amout of reporting
Daniel@0 149 % during training. The argument is used in this function, and it is
Daniel@0 150 % passed to the training functions. To make the function work silently
Daniel@0 151 % set it to 0.
Daniel@0 152 %
Daniel@0 153 % sMap = som_make(D,'tracking',0);
Daniel@0 154 %
Daniel@0 155 % SEE ALSO
Daniel@0 156 %
Daniel@0 157 % som_map_struct Create a map struct.
Daniel@0 158 % som_topol_struct Default values for SOM topology.
Daniel@0 159 % som_train_struct Default values for SOM training parameters.
Daniel@0 160 % som_randinint Random initialization algorithm.
Daniel@0 161 % som_lininit Linear initialization algorithm.
Daniel@0 162 % som_seqtrain Sequential training algorithm.
Daniel@0 163 % som_batchtrain Batch training algorithm.
Daniel@0 164
Daniel@0 165 % Copyright (c) 1999-2000 by the SOM toolbox programming team.
Daniel@0 166 % http://www.cis.hut.fi/projects/somtoolbox/
Daniel@0 167
Daniel@0 168 % Version 2.0beta juuso 111199
Daniel@0 169
Daniel@0 170 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Daniel@0 171 %% check arguments
Daniel@0 172
Daniel@0 173 % D
Daniel@0 174 if isstruct(D)
Daniel@0 175 data_name = D.name;
Daniel@0 176 comp_names = D.comp_names;
Daniel@0 177 comp_norm = D.comp_norm;
Daniel@0 178 D = D.data;
Daniel@0 179 else
Daniel@0 180 data_name = inputname(1);
Daniel@0 181 sDummy = som_data_struct(D(1,:));
Daniel@0 182 comp_names = sDummy.comp_names;
Daniel@0 183 comp_norm = sDummy.comp_norm;
Daniel@0 184 end
Daniel@0 185 [dlen dim] = size(D);
Daniel@0 186
Daniel@0 187 % defaults
Daniel@0 188 mapsize = '';
Daniel@0 189 sM = som_map_struct(dim);
Daniel@0 190 sTopol = sM.topol;
Daniel@0 191 munits = prod(sTopol.msize); % should be zero
Daniel@0 192 mask = sM.mask;
Daniel@0 193 name = sM.name;
Daniel@0 194 neigh = sM.neigh;
Daniel@0 195 tracking = 1;
Daniel@0 196 algorithm = 'batch';
Daniel@0 197 initalg = 'lininit';
Daniel@0 198 training = 'default';
Daniel@0 199
Daniel@0 200 % varargin
Daniel@0 201 i=1;
Daniel@0 202 while i<=length(varargin),
Daniel@0 203 argok = 1;
Daniel@0 204 if ischar(varargin{i}),
Daniel@0 205 switch varargin{i},
Daniel@0 206 % argument IDs
Daniel@0 207 case 'mask', i=i+1; mask = varargin{i};
Daniel@0 208 case 'munits', i=i+1; munits = varargin{i};
Daniel@0 209 case 'msize', i=i+1; sTopol.msize = varargin{i};
Daniel@0 210 munits = prod(sTopol.msize);
Daniel@0 211 case 'mapsize', i=i+1; mapsize = varargin{i};
Daniel@0 212 case 'name', i=i+1; name = varargin{i};
Daniel@0 213 case 'comp_names', i=i+1; comp_names = varargin{i};
Daniel@0 214 case 'lattice', i=i+1; sTopol.lattice = varargin{i};
Daniel@0 215 case 'shape', i=i+1; sTopol.shape = varargin{i};
Daniel@0 216 case {'topol','som_topol','sTopol'},
Daniel@0 217 i=i+1; sTopol = varargin{i}; munits = prod(sTopol.msize);
Daniel@0 218 case 'neigh', i=i+1; neigh = varargin{i};
Daniel@0 219 case 'tracking', i=i+1; tracking = varargin{i};
Daniel@0 220 case 'algorithm', i=i+1; algorithm = varargin{i};
Daniel@0 221 case 'init', i=i+1; initalg = varargin{i};
Daniel@0 222 case 'training', i=i+1; training = varargin{i};
Daniel@0 223 % unambiguous values
Daniel@0 224 case {'hexa','rect'}, sTopol.lattice = varargin{i};
Daniel@0 225 case {'sheet','cyl','toroid'}, sTopol.shape = varargin{i};
Daniel@0 226 case {'gaussian','cutgauss','ep','bubble'}, neigh = varargin{i};
Daniel@0 227 case {'seq','batch','sompak'}, algorithm = varargin{i};
Daniel@0 228 case {'small','normal','big'}, mapsize = varargin{i};
Daniel@0 229 case {'randinit','lininit'}, initalg = varargin{i};
Daniel@0 230 case {'short','default','long'}, training = varargin{i};
Daniel@0 231 otherwise argok=0;
Daniel@0 232 end
Daniel@0 233 elseif isstruct(varargin{i}) & isfield(varargin{i},'type'),
Daniel@0 234 switch varargin{i}(1).type,
Daniel@0 235 case 'som_topol', sTopol = varargin{i};
Daniel@0 236 otherwise argok=0;
Daniel@0 237 end
Daniel@0 238 else
Daniel@0 239 argok = 0;
Daniel@0 240 end
Daniel@0 241 if ~argok,
Daniel@0 242 disp(['(som_make) Ignoring invalid argument #' num2str(i+1)]);
Daniel@0 243 end
Daniel@0 244 i = i+1;
Daniel@0 245 end
Daniel@0 246
Daniel@0 247 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Daniel@0 248 %% make the map struct
Daniel@0 249
Daniel@0 250 %% map size
Daniel@0 251 if isempty(sTopol.msize) | ~prod(sTopol.msize),
Daniel@0 252 if tracking>0, fprintf(1,'Determining map size...\n'); end
Daniel@0 253 if ~munits,
Daniel@0 254 sTemp = som_topol_struct('dlen',dlen);
Daniel@0 255 munits = prod(sTemp.msize);
Daniel@0 256 switch mapsize,
Daniel@0 257 case 'small', munits = max(9,ceil(munits/4));
Daniel@0 258 case 'big', munits = munits*4;
Daniel@0 259 otherwise % nil
Daniel@0 260 end
Daniel@0 261 end
Daniel@0 262 sTemp = som_topol_struct('data',D,'munits',munits);
Daniel@0 263 sTopol.msize = sTemp.msize;
Daniel@0 264 if tracking>0,
Daniel@0 265 fprintf(1,' map size [%d, %d]\n',sTopol.msize(1), sTopol.msize(2));
Daniel@0 266 end
Daniel@0 267 end
Daniel@0 268
Daniel@0 269 % map struct
Daniel@0 270 sMap = som_map_struct(dim,sTopol,neigh,'mask',mask,'name',name, ...
Daniel@0 271 'comp_names', comp_names, 'comp_norm', comp_norm);
Daniel@0 272
Daniel@0 273 % function
Daniel@0 274 if strcmp(algorithm,'sompak'),
Daniel@0 275 algorithm = 'seq';
Daniel@0 276 func = 'sompak';
Daniel@0 277 else
Daniel@0 278 func = algorithm;
Daniel@0 279 end
Daniel@0 280
Daniel@0 281 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Daniel@0 282 %% initialization
Daniel@0 283
Daniel@0 284 if tracking>0, fprintf(1,'Initialization...\n'); end
Daniel@0 285
Daniel@0 286 switch initalg,
Daniel@0 287 case 'randinit', sMap = som_randinit(D, sMap);
Daniel@0 288 case 'lininit', sMap = som_lininit(D, sMap);
Daniel@0 289 end
Daniel@0 290 sMap.trainhist(1) = som_set(sMap.trainhist(1),'data_name',data_name);
Daniel@0 291
Daniel@0 292 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Daniel@0 293 %% training
Daniel@0 294
Daniel@0 295 if tracking>0, fprintf(1,'Training using %s algorithm...\n',algorithm); end
Daniel@0 296
Daniel@0 297 % rough train
Daniel@0 298 if tracking>0, fprintf(1,'Rough training phase...\n'); end
Daniel@0 299 sTrain = som_train_struct(sMap,'dlen',dlen,'algorithm',algorithm,'phase','rough');
Daniel@0 300 sTrain = som_set(sTrain,'data_name',data_name);
Daniel@0 301 if isnumeric(training), sTrain.trainlen = training(1);
Daniel@0 302 else
Daniel@0 303 switch training,
Daniel@0 304 case 'short', sTrain.trainlen = max(1,sTrain.trainlen/4);
Daniel@0 305 case 'long', sTrain.trainlen = sTrain.trainlen*4;
Daniel@0 306 end
Daniel@0 307 end
Daniel@0 308 switch func,
Daniel@0 309 case 'seq', sMap = som_seqtrain(sMap,D,sTrain,'tracking',tracking,'mask',mask);
Daniel@0 310 case 'sompak', sMap = som_sompaktrain(sMap,D,sTrain,'tracking',tracking,'mask',mask);
Daniel@0 311 case 'batch', sMap = som_batchtrain(sMap,D,sTrain,'tracking',tracking,'mask',mask);
Daniel@0 312 end
Daniel@0 313
Daniel@0 314 % finetune
Daniel@0 315 if tracking>0, fprintf(1,'Finetuning phase...\n'); end
Daniel@0 316 sTrain = som_train_struct(sMap,'dlen',dlen,'phase','finetune');
Daniel@0 317 sTrain = som_set(sTrain,'data_name',data_name,'algorithm',algorithm);
Daniel@0 318 if isnumeric(training), sTrain.trainlen = training(2);
Daniel@0 319 else
Daniel@0 320 switch training,
Daniel@0 321 case 'short', sTrain.trainlen = max(1,sTrain.trainlen/4);
Daniel@0 322 case 'long', sTrain.trainlen = sTrain.trainlen*4;
Daniel@0 323 end
Daniel@0 324 end
Daniel@0 325 switch func,
Daniel@0 326 case 'seq', sMap = som_seqtrain(sMap,D,sTrain,'tracking',tracking,'mask',mask);
Daniel@0 327 case 'sompak', sMap = som_sompaktrain(sMap,D,sTrain,'tracking',tracking,'mask',mask);
Daniel@0 328 case 'batch', sMap = som_batchtrain(sMap,D,sTrain,'tracking',tracking,'mask',mask);
Daniel@0 329 end
Daniel@0 330
Daniel@0 331 % quality
Daniel@0 332 if tracking>0,
Daniel@0 333 [mqe,tge] = som_quality(sMap,D);
Daniel@0 334 fprintf(1,'Final quantization error: %5.3f\n',mqe)
Daniel@0 335 fprintf(1,'Final topographic error: %5.3f\n',tge)
Daniel@0 336 end
Daniel@0 337
Daniel@0 338 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Daniel@0 339