wolffd@0: function sTopol = som_topol_struct(varargin) wolffd@0: wolffd@0: %SOM_TOPOL_STRUCT Default values for SOM topology. wolffd@0: % wolffd@0: % sT = som_topol_struct([[argID,] value, ...]) wolffd@0: % wolffd@0: % sTopol = som_topol_struct('data',D); wolffd@0: % sTopol = som_topol_struct('data',D,'munits',200); wolffd@0: % sTopol = som_topol_struct(sTopol); wolffd@0: % sTopol = som_topol_struct; wolffd@0: % wolffd@0: % Input and output arguments ([]'s are optional): wolffd@0: % [argID, (string) Default map topology depends on a number of wolffd@0: % value] (varies) factors (see below). These are given as a wolffd@0: % argument ID - argument value pairs, listed below. wolffd@0: % wolffd@0: % sT (struct) The ready topology struct. wolffd@0: % wolffd@0: % Topology struct contains values for map size, lattice (default is 'hexa') wolffd@0: % and shape (default is 'sheet'). Map size depends on training data and the wolffd@0: % number of map units. The number of map units depends on number of training wolffd@0: % samples. 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: % 'dlen' (scalar) length of the training data wolffd@0: % 'data' (matrix) the training data wolffd@0: % *(struct) the training data wolffd@0: % 'munits' (scalar) number of map units wolffd@0: % 'msize' (vector) map size wolffd@0: % 'lattice' *(string) map lattice: 'hexa' or 'rect' wolffd@0: % 'shape' *(string) map shape: 'sheet', 'cyl' or 'toroid' wolffd@0: % 'topol' *(struct) incomplete topology struct: its empty fields wolffd@0: % will be given values wolffd@0: % 'som_topol','sTopol' = 'topol' wolffd@0: % wolffd@0: % For more help, try 'type som_topol_struct' or check out online documentation. wolffd@0: % See also SOM_SET, SOM_TRAIN_STRUCT, SOM_MAKE. wolffd@0: wolffd@0: %%%%%%%%%%%%% DETAILED DESCRIPTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% wolffd@0: % wolffd@0: % som_topol_struct wolffd@0: % wolffd@0: % PURPOSE wolffd@0: % wolffd@0: % Default values for map topology and training parameters. wolffd@0: % wolffd@0: % SYNTAX wolffd@0: % wolffd@0: % sT = som_topol_struct('argID',value,...); wolffd@0: % sT = som_topol_struct(value,...); wolffd@0: % wolffd@0: % DESCRIPTION wolffd@0: % wolffd@0: % This function is used to give sensible values for map topology (ie. map wolffd@0: % size). The topology struct is returned. wolffd@0: % wolffd@0: % The topology struct has three fields: '.msize', '.lattice' and wolffd@0: % '.shape'. Of these, default value for '.lattice' is 'hexa' and for wolffd@0: % '.shape' 'sheet'. Only the '.msize' field depends on the optional wolffd@0: % arguments: 'dlen', 'munits' and 'data'. The value for '.msize' field is wolffd@0: % determined as follows. wolffd@0: % wolffd@0: % First, the number of map units is determined (unless it is given). A wolffd@0: % heuristic formula of 'munits = 5*sqrt(dlen)' is used to calculate wolffd@0: % it. After this, the map size is determined. Basically, the two biggest wolffd@0: % eigenvalues of the training data are calculated and the ratio between wolffd@0: % sidelengths of the map grid is set to the square root of this ratio. The wolffd@0: % actual sidelengths are then set so that their product is as close to the wolffd@0: % desired number of map units as possible. If the lattice of the grid is wolffd@0: % 'hexa', the ratio is modified a bit to take it into account. If the wolffd@0: % lattice is 'hexa' and shape is 'toroid', the map size along the first axis wolffd@0: % must be even. 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: % 'dlen' (scalar) length of the training data wolffd@0: % 'data' (matrix) the training data wolffd@0: % *(struct) the training data wolffd@0: % 'munits' (scalar) number of map units wolffd@0: % 'msize' (vector) map size wolffd@0: % 'lattice' *(string) map lattice: 'hexa' or 'rect' wolffd@0: % 'shape' *(string) map shape: 'sheet', 'cyl' or 'toroid' wolffd@0: % 'topol' *(struct) incomplete topology struct: its empty fields wolffd@0: % will be given values wolffd@0: % 'som_topol','sTopol' = 'topol' wolffd@0: % wolffd@0: % OUTPUT ARGUMENTS wolffd@0: % wolffd@0: % sT (struct) The topology struct. wolffd@0: % wolffd@0: % EXAMPLES wolffd@0: % wolffd@0: % The most important optional argument for the default topology is 'data'. wolffd@0: % To get a default topology (given data) use: wolffd@0: % wolffd@0: % sTopol = som_topol_struct('data',D); wolffd@0: % wolffd@0: % This sets lattice to its default value 'hexa'. If you want to have a wolffd@0: % 'rect' lattice instead: wolffd@0: % wolffd@0: % sTopol = som_topol_struct('data',D,'lattice','rect'); wolffd@0: % or wolffd@0: % sTopol = som_topol_struct('data',D,'rect'); wolffd@0: % wolffd@0: % If you want to have (close to) a specific number of map units, e.g. 100: wolffd@0: % wolffd@0: % sTopol = som_topol_struct('data',D,'munits',100); wolffd@0: % wolffd@0: % SEE ALSO wolffd@0: % wolffd@0: % som_make Initialize and train a map using default parameters. wolffd@0: % som_train_struct Default training parameters. wolffd@0: % som_randinint Random initialization algorithm. wolffd@0: % som_lininit Linear initialization algorithm. wolffd@0: % som_seqtrain Sequential training algorithm. wolffd@0: % som_batchtrain Batch training algorithm. 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.0alpha juuso 060898 250399 070499 050899 240801 wolffd@0: wolffd@0: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% wolffd@0: %% check arguments wolffd@0: wolffd@0: % initialize wolffd@0: sTopol = som_set('som_topol','lattice','hexa','shape','sheet'); wolffd@0: D = []; wolffd@0: dlen = NaN; wolffd@0: dim = 2; wolffd@0: munits = NaN; wolffd@0: wolffd@0: % varargin 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: case 'dlen', i=i+1; dlen = varargin{i}; wolffd@0: case 'munits', i=i+1; munits = varargin{i}; sTopol.msize = 0; 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 'shape', i=i+1; sTopol.shape = varargin{i}; wolffd@0: case 'data', wolffd@0: i=i+1; wolffd@0: if isstruct(varargin{i}), D = varargin{i}.data; wolffd@0: else D = varargin{i}; wolffd@0: end wolffd@0: [dlen dim] = size(D); wolffd@0: case {'hexa','rect'}, sTopol.lattice = varargin{i}; wolffd@0: case {'sheet','cyl','toroid'}, sTopol.shape = varargin{i}; wolffd@0: case {'som_topol','sTopol','topol'}, wolffd@0: i=i+1; wolffd@0: if ~isempty(varargin{i}.msize) & prod(varargin{i}.msize), wolffd@0: sTopol.msize = varargin{i}.msize; wolffd@0: end wolffd@0: if ~isempty(varargin{i}.lattice), sTopol.lattice = varargin{i}.lattice; end wolffd@0: if ~isempty(varargin{i}.shape), sTopol.shape = varargin{i}.shape; end wolffd@0: otherwise argok=0; wolffd@0: end wolffd@0: elseif isstruct(varargin{i}) & isfield(varargin{i},'type'), wolffd@0: switch varargin{i}.type, wolffd@0: case 'som_topol', wolffd@0: if ~isempty(varargin{i}.msize) & prod(varargin{i}.msize), wolffd@0: sTopol.msize = varargin{i}.msize; wolffd@0: end wolffd@0: if ~isempty(varargin{i}.lattice), sTopol.lattice = varargin{i}.lattice; end wolffd@0: if ~isempty(varargin{i}.shape), sTopol.shape = varargin{i}.shape; end wolffd@0: case 'som_data', wolffd@0: D = varargin{i}.data; wolffd@0: [dlen dim] = size(D); 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_topol_struct) Ignoring invalid argument #' num2str(i)]); wolffd@0: end wolffd@0: i = i+1; wolffd@0: end wolffd@0: wolffd@0: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% wolffd@0: %% action - topology struct wolffd@0: wolffd@0: % lattice and shape set already, so if msize is also set, there's wolffd@0: % nothing else to do wolffd@0: if prod(sTopol.msize) & ~isempty(sTopol.msize), return; end wolffd@0: wolffd@0: % otherwise, decide msize wolffd@0: % first (if necessary) determine the number of map units (munits) wolffd@0: if isnan(munits), wolffd@0: if ~isnan(dlen), wolffd@0: munits = ceil(5 * dlen^0.5); % this is just one way to make a guess... wolffd@0: else wolffd@0: munits = 100; % just a convenient value wolffd@0: end wolffd@0: end wolffd@0: wolffd@0: % then determine the map size (msize) wolffd@0: if dim == 1, % 1-D data wolffd@0: wolffd@0: sTopol.msize = [1 ceil(munits)]; wolffd@0: wolffd@0: elseif size(D,1)<2, % eigenvalues cannot be determined since there's no data wolffd@0: wolffd@0: sTopol.msize = round(sqrt(munits)); wolffd@0: sTopol.msize(2) = round(munits/sTopol.msize(1)); wolffd@0: wolffd@0: else % determine map size based on eigenvalues wolffd@0: wolffd@0: % initialize xdim/ydim ratio using principal components of the input wolffd@0: % space; the ratio is the square root of ratio of two largest eigenvalues wolffd@0: wolffd@0: % autocorrelation matrix wolffd@0: A = zeros(dim)+Inf; wolffd@0: for i=1:dim, D(:,i) = D(:,i) - mean(D(isfinite(D(:,i)),i)); end wolffd@0: for i=1:dim, wolffd@0: for j=i:dim, wolffd@0: c = D(:,i).*D(:,j); c = c(isfinite(c)); wolffd@0: A(i,j) = sum(c)/length(c); A(j,i) = A(i,j); wolffd@0: end wolffd@0: end wolffd@0: % take mdim first eigenvectors with the greatest eigenvalues wolffd@0: [V,S] = eig(A); wolffd@0: eigval = diag(S); wolffd@0: [y,ind] = sort(eigval); wolffd@0: eigval = eigval(ind); wolffd@0: wolffd@0: %me = mean(D); wolffd@0: %D = D - me(ones(length(ind),1),:); % remove mean from data wolffd@0: %eigval = sort(eig((D'*D)./size(D,1))); wolffd@0: if eigval(end)==0 | eigval(end-1)*munits