wolffd@0: function [sMap, sTrain] = som_sompaktrain(sMap, D, varargin) wolffd@0: wolffd@0: %SOM_SOMPAKTRAIN Use SOM_PAK to train the Self-Organizing Map. wolffd@0: % wolffd@0: % [sM,sT] = som_sompaktrain(sM, D, [[argID,] value, ...]) wolffd@0: % wolffd@0: % sM = som_sompaktrain(sM,D); wolffd@0: % sM = som_sompaktrain(sM,sD,'alpha_type','inv'); wolffd@0: % [M,sT] = som_sompaktrain(M,D,'bubble','trainlen',10,'inv','hexa'); wolffd@0: % wolffd@0: % Input and output arguments ([]'s are optional): wolffd@0: % sM (struct) map struct, the trained and updated map is returned wolffd@0: % (matrix) codebook matrix of a self-organizing map wolffd@0: % size munits x dim or msize(1) x ... x msize(k) x dim wolffd@0: % The trained map codebook is returned. wolffd@0: % D (struct) training data; data struct wolffd@0: % (matrix) training data, size dlen x dim wolffd@0: % (string) name of data file wolffd@0: % [argID, (string) See below. The values which are unambiguous can wolffd@0: % value] (varies) be given without the preceeding argID. wolffd@0: % wolffd@0: % sT (struct) learning parameters used during the training wolffd@0: % wolffd@0: % Here are the valid argument IDs and corresponding values. The values which wolffd@0: % are unambiguous (marked with '*') can be given without the preceeding argID. wolffd@0: % 'msize' (vector) map size wolffd@0: % 'radius_ini' (scalar) neighborhood radius wolffd@0: % 'radius' = 'radius_ini' wolffd@0: % 'alpha_ini' (scalar) initial learning rate wolffd@0: % 'alpha' = 'alpha_ini' wolffd@0: % 'trainlen' (scalar) training length wolffd@0: % 'seed' (scalar) seed for random number generator wolffd@0: % 'snapfile' (string) base name for snapshot files wolffd@0: % 'snapinterval' (scalar) snapshot interval wolffd@0: % 'tlen_type' *(string) is the given trainlen 'samples' or 'epochs' wolffd@0: % 'train' *(struct) train struct, parameters for training wolffd@0: % 'sTrain','som_train' = 'train' wolffd@0: % 'alpha_type' *(string) learning rate function, 'inv' or 'linear' wolffd@0: % 'neigh' *(string) neighborhood function, 'gaussian' or 'bubble' wolffd@0: % 'topol' *(struct) topology struct wolffd@0: % 'som_topol','sTopol' = 'topol' wolffd@0: % 'lattice' *(string) map lattice, 'hexa' or 'rect' wolffd@0: % wolffd@0: % For more help, try 'type som_sompaktrain' or check out online documentation. wolffd@0: % See also SOM_MAKE, SOM_SEQTRAIN, SOM_BATCHTRAIN, SOM_TRAIN_STRUCT. wolffd@0: wolffd@0: %%%%%%%%%%%%% DETAILED DESCRIPTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% wolffd@0: % wolffd@0: % som_sompaktrain wolffd@0: % wolffd@0: % PURPOSE wolffd@0: % wolffd@0: % Use SOM_PAK to train the Self-Organizing Map. wolffd@0: % wolffd@0: % SYNTAX wolffd@0: % wolffd@0: % sM = som_sompaktrain(sM,D); wolffd@0: % sM = som_sompaktrain(sM,sD); wolffd@0: % sM = som_sompaktrain(...,'argID',value,...); wolffd@0: % sM = som_sompaktrain(...,value,...); wolffd@0: % [sM,sT] = som_sompaktrain(M,D,...); wolffd@0: % wolffd@0: % DESCRIPTION wolffd@0: % wolffd@0: % Trains the given SOM (sM or M above) with the given training data (sD or wolffd@0: % D) using SOM_PAK. If no optional arguments (argID, value) are wolffd@0: % given, a default training is done, the parameters are obtained from wolffd@0: % SOM_TRAIN_STRUCT function. Using optional arguments the training wolffd@0: % parameters can be specified. Returns the trained and updated SOM and a wolffd@0: % train struct which contains information on the training. wolffd@0: % wolffd@0: % Notice that the SOM_PAK program 'vsom' must be in the search path of your wolffd@0: % shell. Alternatively, you can set a variable 'SOM_PAKDIR' in the Matlab wolffd@0: % workspace to tell the som_sompaktrain where to find the 'vsom' program. wolffd@0: % wolffd@0: % Notice also that many of the training parameters are much more limited in wolffd@0: % values than when using SOM Toolbox function for training: wolffd@0: % - the map shape is always 'sheet' wolffd@0: % - only initial value for neighborhood radius can be given wolffd@0: % - neighborhood function can only be 'bubble' or 'gaussian' wolffd@0: % - only initial value for learning rate can be given wolffd@0: % - learning rate can only be 'linear' or 'inv' wolffd@0: % - mask cannot be used: all variables are always used in BMU search wolffd@0: % Any parameters not confirming to these restrictions will be converted wolffd@0: % so that they do before training. On the other hand, there are some wolffd@0: % additional options that are not present in the SOM Toolbox: wolffd@0: % - random seed wolffd@0: % - snapshot file and interval wolffd@0: % wolffd@0: % REQUIRED INPUT ARGUMENTS wolffd@0: % wolffd@0: % sM The map to be trained. wolffd@0: % (struct) map struct wolffd@0: % (matrix) codebook matrix (field .data of map struct) wolffd@0: % Size is either [munits dim], in which case the map grid wolffd@0: % dimensions (msize) should be specified with optional arguments, wolffd@0: % or [msize(1) ... msize(k) dim] in which case the map wolffd@0: % grid dimensions are taken from the size of the matrix. wolffd@0: % Lattice, by default, is 'rect' and shape 'sheet'. wolffd@0: % D Training data. wolffd@0: % (struct) data struct wolffd@0: % (matrix) data matrix, size [dlen dim] wolffd@0: % (string) name of data file wolffd@0: % wolffd@0: % OPTIONAL INPUT ARGUMENTS wolffd@0: % wolffd@0: % argID (string) Argument identifier string (see below). wolffd@0: % value (varies) Value for the argument (see below). wolffd@0: % wolffd@0: % The optional arguments can be given as 'argID',value -pairs. If an wolffd@0: % argument is given value multiple times, the last one is wolffd@0: % used. The valid IDs and corresponding values are listed below. The values wolffd@0: % which are unambiguous (marked with '*') can be given without the wolffd@0: % preceeding argID. wolffd@0: % wolffd@0: % 'msize' (vector) map grid dimensions. Default is the one wolffd@0: % in sM (field sM.topol.msize) or wolffd@0: % 'si = size(sM); msize = si(1:end-1);' wolffd@0: % if only a codebook matrix was given. wolffd@0: % 'radius_ini' (scalar) initial neighborhood radius wolffd@0: % 'radius' (scalar) = 'radius_ini' wolffd@0: % 'alpha_ini' (vector) initial learning rate wolffd@0: % 'alpha' (scalar) = 'alpha_ini' wolffd@0: % 'trainlen' (scalar) training length (see also 'tlen_type') wolffd@0: % 'seed' (scalar) seed for random number generator wolffd@0: % 'snapfile' (string) base name for snapshot files wolffd@0: % 'snapinterval' (scalar) snapshot interval wolffd@0: % 'tlen_type' *(string) is the trainlen argument given in 'epochs' or wolffd@0: % in 'samples'. Default is 'epochs'. wolffd@0: % 'train' *(struct) train struct, parameters for training. wolffd@0: % Default parameters, unless specified, wolffd@0: % are acquired using SOM_TRAIN_STRUCT (this wolffd@0: % also applies for 'trainlen', 'alpha_type', wolffd@0: % 'alpha_ini', 'radius_ini' and 'radius_fin'). wolffd@0: % 'sTrain', 'som_topol' (struct) = 'train' wolffd@0: % 'neigh' *(string) The used neighborhood function. Default is wolffd@0: % the one in sM (field '.neigh') or 'gaussian' wolffd@0: % if only a codebook matrix was given. The other wolffd@0: % possible value is 'bubble'. wolffd@0: % 'topol' *(struct) topology of the map. Default is the one wolffd@0: % in sM (field '.topol'). wolffd@0: % 'sTopol', 'som_topol' (struct) = 'topol' wolffd@0: % 'alpha_type' *(string) learning rate function, 'inv' or 'linear' wolffd@0: % 'lattice' *(string) map lattice. Default is the one in sM wolffd@0: % (field sM.topol.lattice) or 'rect' wolffd@0: % if only a codebook matrix was given. wolffd@0: % wolffd@0: % OUTPUT ARGUMENTS wolffd@0: % wolffd@0: % sM the trained map wolffd@0: % (struct) if a map struct was given as input argument, a wolffd@0: % map struct is also returned. The current training wolffd@0: % is added to the training history (sM.trainhist). wolffd@0: % The 'neigh' and 'mask' fields of the map struct wolffd@0: % are updated to match those of the training. wolffd@0: % (matrix) if a matrix was given as input argument, a matrix wolffd@0: % is also returned with the same size as the input wolffd@0: % argument. wolffd@0: % sT (struct) train struct; information of the accomplished training wolffd@0: % wolffd@0: % EXAMPLES wolffd@0: % wolffd@0: % Simplest case: wolffd@0: % sM = som_sompaktrain(sM,D); wolffd@0: % sM = som_sompaktrain(sM,sD); wolffd@0: % wolffd@0: % The change training parameters, the optional arguments 'train', wolffd@0: % 'neigh','mask','trainlen','radius','radius_ini', 'alpha', wolffd@0: % 'alpha_type' and 'alpha_ini' are used. wolffd@0: % sM = som_sompaktrain(sM,D,'bubble','trainlen',10,'radius_ini',3); wolffd@0: % wolffd@0: % Another way to specify training parameters is to create a train struct: wolffd@0: % sTrain = som_train_struct(sM,'dlen',size(D,1),'algorithm','seq'); wolffd@0: % sTrain = som_set(sTrain,'neigh','gaussian'); wolffd@0: % sM = som_sompaktrain(sM,D,sTrain); wolffd@0: % wolffd@0: % You don't necessarily have to use the map struct, but you can operate wolffd@0: % directly with codebook matrices. However, in this case you have to wolffd@0: % specify the topology of the map in the optional arguments. The wolffd@0: % following commads are identical (M is originally a 200 x dim sized matrix): wolffd@0: % M = som_sompaktrain(M,D,'msize',[20 10],'lattice','hexa'); wolffd@0: % wolffd@0: % M = som_sompaktrain(M,D,'msize',[20 10],'hexa'); wolffd@0: % wolffd@0: % sT= som_set('som_topol','msize',[20 10],'lattice','hexa'); wolffd@0: % M = som_sompaktrain(M,D,sT); wolffd@0: % wolffd@0: % M = reshape(M,[20 10 dim]); wolffd@0: % M = som_sompaktrain(M,D,'hexa'); wolffd@0: % wolffd@0: % The som_sompaktrain also returns a train struct with information on the wolffd@0: % accomplished training. This is the same one as is added to the end of the wolffd@0: % trainhist field of map struct, in case a map struct is given. wolffd@0: % [M,sTrain] = som_sompaktrain(M,D,'msize',[20 10]); wolffd@0: % wolffd@0: % [sM,sTrain] = som_sompaktrain(sM,D); % sM.trainhist(end)==sTrain wolffd@0: % wolffd@0: % SEE ALSO wolffd@0: % wolffd@0: % som_make Initialize and train a SOM using default parameters. wolffd@0: % som_seqtrain Train SOM with sequential algorithm. wolffd@0: % som_batchtrain Train SOM with batch algorithm. wolffd@0: % som_train_struct Determine default training parameters. wolffd@0: wolffd@0: % Copyright (c) 1999-2000 by the SOM toolbox programming team. wolffd@0: % http://www.cis.hut.fi/projects/somtoolbox/ wolffd@0: wolffd@0: % Version 2.0beta juuso 151199 wolffd@0: wolffd@0: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% wolffd@0: %% Check arguments wolffd@0: wolffd@0: error(nargchk(2, Inf, nargin)); % check the number of input arguments wolffd@0: wolffd@0: % map wolffd@0: struct_mode = isstruct(sMap); wolffd@0: if struct_mode, wolffd@0: sTopol = sMap.topol; wolffd@0: else wolffd@0: orig_size = size(sMap); wolffd@0: if ndims(sMap) > 2, wolffd@0: si = size(sMap); dim = si(end); msize = si(1:end-1); wolffd@0: M = reshape(sMap,[prod(msize) dim]); wolffd@0: else wolffd@0: msize = [orig_size(1) 1]; wolffd@0: dim = orig_size(2); wolffd@0: end wolffd@0: sMap = som_map_struct(dim,'msize',msize); wolffd@0: sTopol = sMap.topol; wolffd@0: end wolffd@0: [munits dim] = size(sMap.codebook); wolffd@0: wolffd@0: % data wolffd@0: givendatafile = ''; wolffd@0: if ischar(D), wolffd@0: data_name = D; wolffd@0: givendatafile = D; wolffd@0: D = []; wolffd@0: dlen = NaN; wolffd@0: else wolffd@0: if isstruct(D), wolffd@0: data_name = D.name; wolffd@0: D = D.data; wolffd@0: else wolffd@0: data_name = inputname(2); wolffd@0: end wolffd@0: D = D(find(sum(isnan(D),2) < dim),:); % remove empty vectors from the data wolffd@0: [dlen ddim] = size(D); % check input dimension wolffd@0: if ddim ~= dim, error('Map and data dimensions must agree.'); end wolffd@0: end wolffd@0: wolffd@0: % varargin wolffd@0: sTrain = som_set('som_train','algorithm','seq',... wolffd@0: 'neigh',sMap.neigh,... wolffd@0: 'mask',ones(dim,1),... wolffd@0: 'data_name',data_name); wolffd@0: tlen_type = 'epochs'; wolffd@0: random_seed = 0; wolffd@0: snapshotname = ''; wolffd@0: snapshotinterval = 0; wolffd@0: wolffd@0: i=1; wolffd@0: while i<=length(varargin), wolffd@0: argok = 1; wolffd@0: if ischar(varargin{i}), wolffd@0: switch varargin{i}, wolffd@0: % argument IDs wolffd@0: case 'msize', i=i+1; sTopol.msize = varargin{i}; wolffd@0: case 'lattice', i=i+1; sTopol.lattice = varargin{i}; wolffd@0: case 'neigh', i=i+1; sTrain.neigh = varargin{i}; wolffd@0: case 'trainlen', i=i+1; sTrain.trainlen = varargin{i}; wolffd@0: case 'tlen_type', i=i+1; tlen_type = varargin{i}; wolffd@0: case 'radius_ini', i=i+1; sTrain.radius_ini = varargin{i}; wolffd@0: case 'radius', i=i+1; sTrain.radius_ini = varargin{i}(1); wolffd@0: case 'alpha_type', i=i+1; sTrain.alpha_type = varargin{i}; wolffd@0: case 'alpha_ini', i=i+1; sTrain.alpha_ini = varargin{i}; wolffd@0: case 'alpha', i=i+1; sTrain.alpha_ini = varargin{i}(1); wolffd@0: case 'seed', i=i+1; random_seed = varargin{i}; wolffd@0: case 'snapshotname',i=i+1; snapshotname = varargin{i}; wolffd@0: case 'snapshotinterval',i=i+1; snapshotinterval = varargin{i}; wolffd@0: case {'sTrain','train','som_train'}, i=i+1; sTrain = varargin{i}; wolffd@0: case {'topol','sTopol','som_topol'}, wolffd@0: i=i+1; wolffd@0: sTopol = varargin{i}; wolffd@0: if prod(sTopol.msize) ~= munits, wolffd@0: error('Given map grid size does not match the codebook size.'); wolffd@0: end wolffd@0: % unambiguous values wolffd@0: case {'inv','linear'}, sTrain.alpha_type = varargin{i}; wolffd@0: case {'hexa','rect'}, sTopol.lattice = varargin{i}; wolffd@0: case {'gaussian','bubble'}, sTrain.neigh = varargin{i}; wolffd@0: case {'epochs','samples'}, tlen_type = varargin{i}; wolffd@0: otherwise argok=0; wolffd@0: end wolffd@0: elseif isstruct(varargin{i}) & isfield(varargin{i},'type'), wolffd@0: switch varargin{i}(1).type, wolffd@0: case 'som_topol', wolffd@0: sTopol = varargin{i}; wolffd@0: if prod(sTopol.msize) ~= munits, wolffd@0: error('Given map grid size does not match the codebook size.'); wolffd@0: end wolffd@0: case 'som_train', sTrain = varargin{i}; wolffd@0: otherwise argok=0; wolffd@0: end wolffd@0: else wolffd@0: argok = 0; wolffd@0: end wolffd@0: if ~argok, wolffd@0: disp(['(som_sompaktrain) Ignoring invalid argument #' num2str(i+2)]); wolffd@0: end wolffd@0: i = i+1; wolffd@0: end wolffd@0: wolffd@0: % check topology wolffd@0: if struct_mode, wolffd@0: if ~strcmp(sTopol.lattice,sMap.topol.lattice) | ... wolffd@0: ~strcmp(sTopol.shape,sMap.topol.shape) | ... wolffd@0: any(sTopol.msize ~= sMap.topol.msize), wolffd@0: warning('Changing the original map topology.'); wolffd@0: end wolffd@0: end wolffd@0: sMap.topol = sTopol; wolffd@0: wolffd@0: % complement the training struct wolffd@0: if ~isnan(dlen), wolffd@0: sTrain = som_train_struct(sTrain,sMap,'dlen',dlen); wolffd@0: else wolffd@0: sTrain = som_train_struct(sTrain,sMap); wolffd@0: end wolffd@0: if isempty(sTrain.mask), sTrain.mask = ones(dim,1); end wolffd@0: wolffd@0: % training length wolffd@0: if strcmp(tlen_type,'epochs'), wolffd@0: if isnan(dlen), wolffd@0: error('Training length given as epochs, but data length is not known.\n'); wolffd@0: else wolffd@0: rlen = sTrain.trainlen*dlen; wolffd@0: end wolffd@0: else wolffd@0: rlen = sTrain.trainlen; wolffd@0: sTrain.trainlen = sTrain.trainlen/dlen; wolffd@0: end wolffd@0: wolffd@0: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% wolffd@0: %% check arguments wolffd@0: wolffd@0: % mask wolffd@0: if any(sTrain.mask~=1), wolffd@0: sTrain.mask = ones(dim,1); wolffd@0: fprintf(1,'Ignoring given mask.\n'); wolffd@0: end wolffd@0: wolffd@0: % learning rate wolffd@0: if strcmp(sTrain.alpha_type,'power'), wolffd@0: sTrain.alpha_type = 'inv'; wolffd@0: fprintf(1,'Using ''inv'' learning rate type instead of ''power''\n'); wolffd@0: end wolffd@0: wolffd@0: % neighborhood wolffd@0: if any(strcmp(sTrain.neigh,{'cutgauss','ep'})), wolffd@0: fprintf(1,'Using ''gaussian'' neighborhood function instead of %s.\n',sTrain.neigh); wolffd@0: sTrain.neigh = 'gaussian'; wolffd@0: end wolffd@0: wolffd@0: % map shape wolffd@0: if ~strcmp(sMap.topol.shape,'sheet'), wolffd@0: fprintf(1,'Using ''sheet'' map shape of %s.\n',sMap.topol.shape); wolffd@0: sMap.topol.shape = 'sheet'; wolffd@0: end wolffd@0: wolffd@0: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% wolffd@0: %% Action wolffd@0: wolffd@0: % write files wolffd@0: if ~isempty(givendatafile), wolffd@0: temp_din = givendatafile; wolffd@0: else wolffd@0: temp_din = tempname; wolffd@0: som_write_data(D, temp_din, 'x') wolffd@0: end wolffd@0: temp_cin = tempname; wolffd@0: som_write_cod(sMap, temp_cin) wolffd@0: temp_cout = tempname; wolffd@0: wolffd@0: % check if the environment variable 'SOM_PAKDIR' has been defined wolffd@0: if any(strcmp('SOM_PAKDIR', evalin('base', 'who'))) wolffd@0: som_pak_dir = evalin('base', 'SOM_PAKDIR'); wolffd@0: else wolffd@0: som_pak_dir = ''; wolffd@0: end wolffd@0: if ~isempty(som_pak_dir) & ~strncmp(som_pak_dir(end), '/', 1) wolffd@0: som_pak_dir(end + 1) = '/'; wolffd@0: end wolffd@0: wolffd@0: aini = sTrain.alpha_ini; wolffd@0: atype = sTrain.alpha_type; wolffd@0: if strcmp(atype,'inv'), atype = 'inverse_t'; end wolffd@0: rad = sTrain.radius_ini; wolffd@0: str = [som_pak_dir 'vsom ' ... wolffd@0: sprintf('-cin %s -din %s -cout %s', temp_cin, temp_din, temp_cout) ... wolffd@0: sprintf(' -rlen %d -alpha %g -alpha_type %s', rlen, aini, atype) ... wolffd@0: sprintf(' -radius %g -rand %g ',rad,random_seed)]; wolffd@0: if ~isempty(snapshotname) & snapinterval>0, wolffd@0: str = [str, sprintf(' -snapfile %s -snapinterval %d',snapshotname,snapshotinterval)]; wolffd@0: end wolffd@0: wolffd@0: fprintf(1,'Execute: %s\n',str); wolffd@0: if isunix, wolffd@0: [status,w] = unix(str); wolffd@0: if status, fprintf(1,'Execution failed.\n'); end wolffd@0: if ~isempty(w), fprintf(1,'%s\n',w); end wolffd@0: else wolffd@0: [status,w] = dos(str); wolffd@0: if status, fprintf(1,'Execution failed.\n'); end wolffd@0: if ~isempty(w), fprintf(1,'%s\n',w); end wolffd@0: end wolffd@0: wolffd@0: sMap_temp = som_read_cod(temp_cout); wolffd@0: M = sMap_temp.codebook; wolffd@0: wolffd@0: if isunix wolffd@0: unix(['/bin/rm -f ' temp_din ' ' temp_cin ' ' temp_cout]); wolffd@0: else wolffd@0: dos(['del ' temp_din ' ' temp_cin ' ' temp_cout]); wolffd@0: end wolffd@0: wolffd@0: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% wolffd@0: %% Build / clean up the return arguments wolffd@0: wolffd@0: % update structures wolffd@0: sTrain = som_set(sTrain,'time',datestr(now,0)); wolffd@0: if struct_mode, wolffd@0: sMap = som_set(sMap,'codebook',M,'mask',sTrain.mask,'neigh',sTrain.neigh); wolffd@0: tl = length(sMap.trainhist); wolffd@0: sMap.trainhist(tl+1) = sTrain; wolffd@0: else wolffd@0: sMap = reshape(M,orig_size); wolffd@0: end wolffd@0: wolffd@0: return; wolffd@0: wolffd@0: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% wolffd@0: