Daniel@0: function sTrain = som_train_struct(varargin) Daniel@0: Daniel@0: %SOM_TRAIN_STRUCT Default values for SOM training parameters. Daniel@0: % Daniel@0: % sT = som_train_struct([[argID,] value, ...]) Daniel@0: % Daniel@0: % sTrain = som_train_struct('train',sM,sD); Daniel@0: % sTrain = som_train_struct('finetune','data',D); Daniel@0: % sTrain = som_train_struct('previous',sT0); Daniel@0: % Daniel@0: % Input and output arguments ([]'s are optional): Daniel@0: % [argID, (string) Several default values depend on other SOM parameters Daniel@0: % value] (varies) or on the proporties of a data set. See below for a Daniel@0: % a list of required and optional arguments for Daniel@0: % different parameters, and well as the list of valid Daniel@0: % argIDs and associated values. The values which are Daniel@0: % unambiguous can be given without the preceeding argID. Daniel@0: % Daniel@0: % sT (struct) The training struct. Daniel@0: % Daniel@0: % Training struct contains values for training and initialization Daniel@0: % parameters. These parameters depend on the number of training samples, Daniel@0: % phase of training, the training algorithm. Daniel@0: % Daniel@0: % Here are the valid argument IDs and corresponding values. The values which Daniel@0: % are unambiguous (marked with '*') can be given without the preceeding rgID. Daniel@0: % 'dim' (scalar) input space dimension Daniel@0: % 'dlen' (scalar) length of the training data Daniel@0: % 'data' (matrix / struct) the training data Daniel@0: % 'munits' (scalar) number of map units Daniel@0: % 'msize' (vector) map size Daniel@0: % 'previous' (struct) previous training struct can be given in Daniel@0: % conjunction with 'finetune' phase (see below) Daniel@0: % 'phase' *(string) training phase: 'init', 'train', 'rough' or 'finetune' Daniel@0: % 'algorithm' *(string) algorithm to use: 'lininit', 'randinit', 'batch' or 'seq' Daniel@0: % 'map' *(struct) If a map struct is given, the last training struct Daniel@0: % in '.trainhist' field is used as the previous training Daniel@0: % struct. The map size and input space dimension are Daniel@0: % extracted from the map struct. Daniel@0: % 'sTrain' *(struct) a train struct, the empty fields of which are Daniel@0: % filled with sensible values Daniel@0: % Daniel@0: % For more help, try 'type som_train_struct' or check out online documentation. Daniel@0: % See also SOM_SET, SOM_TOPOL_STRUCT, SOM_MAKE. Daniel@0: Daniel@0: %%%%%%%%%%%%% DETAILED DESCRIPTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Daniel@0: % Daniel@0: % som_train_struct Daniel@0: % Daniel@0: % PURPOSE Daniel@0: % Daniel@0: % Default values for SOM training parameters. Daniel@0: % Daniel@0: % SYNTAX Daniel@0: % Daniel@0: % sT = som_train_struct('argID',value,...); Daniel@0: % sT = som_train_struct(value,...); Daniel@0: % Daniel@0: % DESCRIPTION Daniel@0: % Daniel@0: % This function is used to give sensible values for SOM training Daniel@0: % parameters and returns a training struct. Often, the parameters Daniel@0: % depend on the properties of the map and the training data. These are Daniel@0: % given as optional arguments to the function. If a partially filled Daniel@0: % train struct is given, its empty fields (field value is [] or '' or Daniel@0: % NaN) are supplimented with default values. Daniel@0: % Daniel@0: % The training struct has a number of fields which depend on each other Daniel@0: % and the optional arguments in complex ways. The most important argument Daniel@0: % is 'phase' which can be either 'init', 'train', 'rough' or 'finetune'. Daniel@0: % Daniel@0: % 'init' Map initialization. Daniel@0: % 'train' Map training in a onepass operation, as opposed to the Daniel@0: % rough-finetune combination. Daniel@0: % 'rough' Rough organization of the map: large neighborhood, big Daniel@0: % initial value for learning coefficient. Short training. Daniel@0: % 'finetune' Finetuning the map after rough organization phase. Small Daniel@0: % neighborhood, learning coefficient is small already at Daniel@0: % the beginning. Long training. Daniel@0: % Daniel@0: % The fields of training struct set by this function are listed below. Daniel@0: % Daniel@0: % '.mask' Basically, a column vector of ones. But if a previous Daniel@0: % train or map struct is given, it is copied from there. Daniel@0: % '.neigh' Default value is 'gaussian' but if a previous train or map Daniel@0: % struct is given, it is copied from there. Daniel@0: % '.alpha_type' Default value is 'inv' but if a previous training struct Daniel@0: % is given, it is copied from there. Daniel@0: % '.alpha_ini' For 'train' and 'rough' phases, this is 0.5, for Daniel@0: % 'finetune' it is 0.05. Daniel@0: % '.radius_ini' Depends on the previous training operation and the Daniel@0: % maximum sidelength of the map ms = max(msize). Daniel@0: % if there isn't one, or it is 'randinit', rad_ini = max(1,ms/2) Daniel@0: % if it is 'lininit', rad_ini = max(1,ms/8) Daniel@0: % otherwise, rad_ini = rad_fin of the previous training Daniel@0: % '.radius_fin' Default value is 1, but if the training phase is Daniel@0: % 'rough', rad_fin = max(1,rad_ini/4). Daniel@0: % '.trainlen' For 'train' phase this is 20 x mpd epochs, for 'rough' Daniel@0: % phase 4 x mpd epochs and for 'finetune' 16 x mpd Daniel@0: % epochs, where mpd = munits/dlen. If mpd cannot be Daniel@0: % calculated, it is set to be = 0.5. In any case, Daniel@0: % trainlen is at least one epoch. Daniel@0: % '.algorithm' Default training algorithm is 'batch' and default Daniel@0: % initialization algorithm is 'lininit'. Daniel@0: % Daniel@0: % OPTIONAL INPUT ARGUMENTS Daniel@0: % Daniel@0: % argID (string) Argument identifier string (see below). Daniel@0: % value (varies) Value for the argument (see below). Daniel@0: % Daniel@0: % The optional arguments can be given as 'argID',value -pairs. If an Daniel@0: % argument is given value multiple times, the last one is used. The Daniel@0: % valid IDs and corresponding values are listed below. The values Daniel@0: % which are unambiguous (marked with '*') can be given without the Daniel@0: % preceeding argID. Daniel@0: % Daniel@0: % 'dim' (scalar) input space dimension Daniel@0: % 'dlen' (scalar) length of the training data Daniel@0: % 'data' (matrix / struct) the training data Daniel@0: % 'munits' (scalar) number of map units Daniel@0: % 'msize' (vector) map size Daniel@0: % 'previous' (struct) previous training struct can be given in Daniel@0: % conjunction with 'finetune' phase. Daniel@0: % 'phase' *(string) training phase: 'init', 'train', 'rough' or 'finetune' Daniel@0: % 'algorithm' *(string) algorithm to use: 'lininit', 'randinit', Daniel@0: % 'batch' or 'seq' Daniel@0: % 'map' *(struct) If a map struc is given, the last training struct Daniel@0: % in '.trainhist' field is used as the previous training Daniel@0: % struct. The map size and input space dimension are Daniel@0: % extracted from the map struct. Daniel@0: % 'sTrain' *(struct) a train struct, the empty fields of which are Daniel@0: % filled with sensible values Daniel@0: % Daniel@0: % OUTPUT ARGUMENTS Daniel@0: % Daniel@0: % sT (struct) The training struct. Daniel@0: % Daniel@0: % EXAMPLES Daniel@0: % Daniel@0: % The most important optional argument for the training parameters is Daniel@0: % 'phase'. The second most important are 'previous' and/or 'map'. Daniel@0: % Daniel@0: % To get default initialization parameters, use: Daniel@0: % Daniel@0: % sTrain = som_train_struct('phase','init'); Daniel@0: % or Daniel@0: % sTrain = som_train_struct('init'); Daniel@0: % Daniel@0: % To get default training parameters, use: Daniel@0: % Daniel@0: % sTrain = som_train_struct('phase','train','data',D,'map',sMap); Daniel@0: % or Daniel@0: % sTrain = som_train_struct('train','data',D,sMap); Daniel@0: % or Daniel@0: % sTrain = som_train_struct('train','dlen',dlen, ... Daniel@0: % 'msize',sMap.topol.msize,'dim',dim); Daniel@0: % Daniel@0: % If you want to first rough train and then finetune, do like this: Daniel@0: % Daniel@0: % sT1 = som_train_struct('rough','dlen',length(D),sMap); % rough training Daniel@0: % sT2 = som_train_struct('finetune','previous',sT1); % finetuning Daniel@0: % Daniel@0: % SEE ALSO Daniel@0: % Daniel@0: % som_make Initialize and train a map using default parameters. Daniel@0: % som_topol_struct Default map topology. Daniel@0: % som_randinint Random initialization algorithm. Daniel@0: % som_lininit Linear initialization algorithm. Daniel@0: % som_seqtrain Sequential training algorithm. Daniel@0: % som_batchtrain Batch training algorithm. Daniel@0: Daniel@0: % Copyright (c) 1999-2000 by the SOM toolbox programming team. Daniel@0: % http://www.cis.hut.fi/projects/somtoolbox/ Daniel@0: Daniel@0: % Version 2.0beta juuso 101199 090200 210301 Daniel@0: Daniel@0: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Daniel@0: %% check arguments Daniel@0: Daniel@0: % initial default structs Daniel@0: sTrain = som_set('som_train'); Daniel@0: Daniel@0: % initialize optional parameters Daniel@0: dlen = NaN; Daniel@0: msize = 0; Daniel@0: munits = NaN; Daniel@0: sTprev = []; Daniel@0: dim = NaN; Daniel@0: phase = ''; Daniel@0: Daniel@0: % varargin Daniel@0: i=1; Daniel@0: while i<=length(varargin), Daniel@0: argok = 1; Daniel@0: if ischar(varargin{i}), Daniel@0: switch varargin{i}, Daniel@0: case 'dim', i=i+1; dim = varargin{i}; Daniel@0: case 'dlen', i=i+1; dlen = varargin{i}; Daniel@0: case 'msize', i=i+1; msize = varargin{i}; Daniel@0: case 'munits', i=i+1; munits = varargin{i}; msize = 0; Daniel@0: case 'phase', i=i+1; phase = varargin{i}; Daniel@0: case 'algorithm', i=i+1; sTrain.algorithm = varargin{i}; Daniel@0: case 'mask', i=i+1; sTrain.mask = varargin{i}; Daniel@0: case {'previous','map'}, Daniel@0: i=i+1; Daniel@0: if strcmp(varargin{i}.type,'som_map'), Daniel@0: if length(varargin{i}.trainhist), Daniel@0: sTprev = varargin{i}.trainhist(end); Daniel@0: msize = varargin{i}.topol.msize; Daniel@0: end Daniel@0: elseif strcmp(varargin{i}.type,'som_train'), Daniel@0: sTprev = varargin{i}; Daniel@0: end Daniel@0: case 'data', Daniel@0: i=i+1; Daniel@0: if isstruct(varargin{i}), [dlen dim] = size(varargin{i}.data); Daniel@0: else [dlen dim] = size(varargin{i}); Daniel@0: end Daniel@0: case {'init','train','rough','finetune'}, phase = varargin{i}; Daniel@0: case {'lininit','randinit','seq','batch'}, sTrain.algorithm = varargin{i}; Daniel@0: otherwise argok=0; Daniel@0: end Daniel@0: elseif isstruct(varargin{i}) & isfield(varargin{i},'type'), Daniel@0: switch varargin{i}.type, Daniel@0: case 'som_train', Daniel@0: sT = varargin{i}; Daniel@0: if ~isempty(sT.algorithm), sTrain.algorithm = sT.algorithm; end Daniel@0: if ~isempty(sT.neigh), sTrain.neigh = sT.neigh; end Daniel@0: if ~isempty(sT.mask), sTrain.mask = sT.mask; end Daniel@0: if ~isnan(sT.radius_ini), sTrain.radius_ini = sT.radius_ini; end Daniel@0: if ~isnan(sT.radius_fin), sTrain.radius_fin = sT.radius_fin; end Daniel@0: if ~isnan(sT.alpha_ini), sTrain.alpha_ini = sT.alpha_ini; end Daniel@0: if ~isempty(sT.alpha_type), sTrain.alpha_type = sT.alpha_type; end Daniel@0: if ~isnan(sT.trainlen), sTrain.trainlen = sT.trainlen; end Daniel@0: if ~isempty(sT.data_name), sTrain.data_name = sT.data_name; end Daniel@0: if ~isempty(sT.time), sTrain.time = sT.time; end Daniel@0: case 'som_map', Daniel@0: if strcmp(varargin{i}.type,'som_map'), Daniel@0: if length(varargin{i}.trainhist), Daniel@0: sTprev = varargin{i}.trainhist(end); Daniel@0: msize = varargin{i}.topol.msize; Daniel@0: end Daniel@0: if ~isempty(varargin{i}.neigh) & isempty(sTrain.neigh), Daniel@0: sTrain.neigh = varargin{i}.neigh; Daniel@0: end Daniel@0: if ~isempty(varargin{i}.mask) & isempty(sTrain.mask), Daniel@0: sTrain.mask = varargin{i}.mask; Daniel@0: end Daniel@0: elseif strcmp(varargin{i}.type,'som_train'), Daniel@0: sTprev = varargin{i}; Daniel@0: end Daniel@0: case 'som_topol', msize = varargin{i}.msize; Daniel@0: case 'som_data', [dlen dim] = size(varargin{i}.data); Daniel@0: otherwise argok=0; Daniel@0: end Daniel@0: else Daniel@0: argok = 0; Daniel@0: end Daniel@0: if ~argok, Daniel@0: disp(['(som_train_struct) Ignoring invalid argument #' num2str(i)]); Daniel@0: end Daniel@0: i = i+1; Daniel@0: end Daniel@0: Daniel@0: % dim Daniel@0: if ~isempty(sTprev) & isnan(dim), dim = length(sTprev.mask); end Daniel@0: Daniel@0: % mask Daniel@0: if isempty(sTrain.mask) & ~isnan(dim), sTrain.mask = ones(dim,1); end Daniel@0: Daniel@0: % msize, munits Daniel@0: if ~msize | isempty(msize), Daniel@0: if isnan(munits), msize = [10 10]; Daniel@0: else s = round(sqrt(munits)); msize = [s round(munits/s)]; Daniel@0: end Daniel@0: end Daniel@0: munits = prod(msize); Daniel@0: Daniel@0: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Daniel@0: %% action Daniel@0: Daniel@0: % previous training Daniel@0: prevalg = ''; Daniel@0: if ~isempty(sTprev), Daniel@0: if any(findstr(sTprev.algorithm,'init')), prevalg = 'init'; Daniel@0: else prevalg = sTprev.algorithm; Daniel@0: end Daniel@0: end Daniel@0: Daniel@0: % first determine phase Daniel@0: if isempty(phase), Daniel@0: switch sTrain.algorithm, Daniel@0: case {'lininit','randinit'}, phase = 'init'; Daniel@0: case {'batch','seq',''}, Daniel@0: if isempty(sTprev), phase = 'rough'; Daniel@0: elseif strcmp(prevalg,'init'), phase = 'rough'; Daniel@0: else phase = 'finetune'; Daniel@0: end Daniel@0: otherwise, phase = 'train'; Daniel@0: end Daniel@0: end Daniel@0: Daniel@0: % then determine algorithm Daniel@0: if isempty(sTrain.algorithm), Daniel@0: if strcmp(phase,'init'), sTrain.algorithm = 'lininit'; Daniel@0: elseif any(strcmp(prevalg,{'init',''})), sTrain.algorithm = 'batch'; Daniel@0: else sTrain.algorithm = sTprev.algorithm; Daniel@0: end Daniel@0: end Daniel@0: Daniel@0: % mask Daniel@0: if isempty(sTrain.mask), Daniel@0: if ~isempty(sTprev), sTrain.mask = sTprev.mask; Daniel@0: elseif ~isnan(dim), sTrain.mask = ones(dim,1); Daniel@0: end Daniel@0: end Daniel@0: Daniel@0: % neighborhood function Daniel@0: if isempty(sTrain.neigh), Daniel@0: if ~isempty(sTprev) & ~isempty(sTprev.neigh), sTrain.neigh = sTprev.neigh; Daniel@0: else sTrain.neigh = 'gaussian'; Daniel@0: end Daniel@0: end Daniel@0: Daniel@0: if strcmp(phase,'init'), Daniel@0: sTrain.alpha_ini = NaN; Daniel@0: sTrain.alpha_type = ''; Daniel@0: sTrain.radius_ini = NaN; Daniel@0: sTrain.radius_fin = NaN; Daniel@0: sTrain.trainlen = NaN; Daniel@0: sTrain.neigh = ''; Daniel@0: else Daniel@0: mode = [phase, '-', sTrain.algorithm]; Daniel@0: Daniel@0: % learning rate Daniel@0: if isnan(sTrain.alpha_ini), Daniel@0: if strcmp(sTrain.algorithm,'batch'), sTrain.alpha_ini = NaN; Daniel@0: else Daniel@0: switch phase, Daniel@0: case {'train','rough'}, sTrain.alpha_ini = 0.5; Daniel@0: case 'finetune', sTrain.alpha_ini = 0.05; Daniel@0: end Daniel@0: end Daniel@0: end Daniel@0: if isempty(sTrain.alpha_type), Daniel@0: if ~isempty(sTprev) & ~isempty(sTprev.alpha_type) ... Daniel@0: & ~strcmp(sTrain.algorithm,'batch'), Daniel@0: sTrain.alpha_type = sTprev.alpha_type; Daniel@0: elseif strcmp(sTrain.algorithm,'seq'), Daniel@0: sTrain.alpha_type = 'inv'; Daniel@0: end Daniel@0: end Daniel@0: Daniel@0: % radius Daniel@0: ms = max(msize); Daniel@0: if isnan(sTrain.radius_ini), Daniel@0: if isempty(sTprev) | strcmp(sTprev.algorithm,'randinit'), Daniel@0: sTrain.radius_ini = max(1,ceil(ms/4)); Daniel@0: elseif strcmp(sTprev.algorithm,'lininit') | isnan(sTprev.radius_fin), Daniel@0: sTrain.radius_ini = max(1,ceil(ms/8)); Daniel@0: else Daniel@0: sTrain.radius_ini = sTprev.radius_fin; Daniel@0: end Daniel@0: end Daniel@0: if isnan(sTrain.radius_fin), Daniel@0: if strcmp(phase,'rough'), Daniel@0: sTrain.radius_fin = max(1,sTrain.radius_ini/4); Daniel@0: else Daniel@0: sTrain.radius_fin = 1; Daniel@0: end Daniel@0: end Daniel@0: Daniel@0: % trainlen Daniel@0: if isnan(sTrain.trainlen), Daniel@0: mpd = munits/dlen; Daniel@0: if isnan(mpd), mpd = 0.5; end Daniel@0: switch phase, Daniel@0: case 'train', sTrain.trainlen = ceil(50*mpd); Daniel@0: case 'rough', sTrain.trainlen = ceil(10*mpd); Daniel@0: case 'finetune', sTrain.trainlen = ceil(40*mpd); Daniel@0: end Daniel@0: sTrain.trainlen = max(1,sTrain.trainlen); Daniel@0: end Daniel@0: Daniel@0: end Daniel@0: Daniel@0: return; Daniel@0: Daniel@0: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%