Mercurial > hg > camir-aes2014
diff toolboxes/MIRtoolbox1.3.2/somtoolbox/som_topol_struct.m @ 0:e9a9cd732c1e tip
first hg version after svn
author | wolffd |
---|---|
date | Tue, 10 Feb 2015 15:05:51 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/toolboxes/MIRtoolbox1.3.2/somtoolbox/som_topol_struct.m Tue Feb 10 15:05:51 2015 +0000 @@ -0,0 +1,272 @@ +function sTopol = som_topol_struct(varargin) + +%SOM_TOPOL_STRUCT Default values for SOM topology. +% +% sT = som_topol_struct([[argID,] value, ...]) +% +% sTopol = som_topol_struct('data',D); +% sTopol = som_topol_struct('data',D,'munits',200); +% sTopol = som_topol_struct(sTopol); +% sTopol = som_topol_struct; +% +% Input and output arguments ([]'s are optional): +% [argID, (string) Default map topology depends on a number of +% value] (varies) factors (see below). These are given as a +% argument ID - argument value pairs, listed below. +% +% sT (struct) The ready topology struct. +% +% Topology struct contains values for map size, lattice (default is 'hexa') +% and shape (default is 'sheet'). Map size depends on training data and the +% number of map units. The number of map units depends on number of training +% samples. +% +% Here are the valid argument IDs and corresponding values. The values which +% are unambiguous (marked with '*') can be given without the preceeding argID. +% 'dlen' (scalar) length of the training data +% 'data' (matrix) the training data +% *(struct) the training data +% 'munits' (scalar) number of map units +% 'msize' (vector) map size +% 'lattice' *(string) map lattice: 'hexa' or 'rect' +% 'shape' *(string) map shape: 'sheet', 'cyl' or 'toroid' +% 'topol' *(struct) incomplete topology struct: its empty fields +% will be given values +% 'som_topol','sTopol' = 'topol' +% +% For more help, try 'type som_topol_struct' or check out online documentation. +% See also SOM_SET, SOM_TRAIN_STRUCT, SOM_MAKE. + +%%%%%%%%%%%%% DETAILED DESCRIPTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% som_topol_struct +% +% PURPOSE +% +% Default values for map topology and training parameters. +% +% SYNTAX +% +% sT = som_topol_struct('argID',value,...); +% sT = som_topol_struct(value,...); +% +% DESCRIPTION +% +% This function is used to give sensible values for map topology (ie. map +% size). The topology struct is returned. +% +% The topology struct has three fields: '.msize', '.lattice' and +% '.shape'. Of these, default value for '.lattice' is 'hexa' and for +% '.shape' 'sheet'. Only the '.msize' field depends on the optional +% arguments: 'dlen', 'munits' and 'data'. The value for '.msize' field is +% determined as follows. +% +% First, the number of map units is determined (unless it is given). A +% heuristic formula of 'munits = 5*sqrt(dlen)' is used to calculate +% it. After this, the map size is determined. Basically, the two biggest +% eigenvalues of the training data are calculated and the ratio between +% sidelengths of the map grid is set to the square root of this ratio. The +% actual sidelengths are then set so that their product is as close to the +% desired number of map units as possible. If the lattice of the grid is +% 'hexa', the ratio is modified a bit to take it into account. If the +% lattice is 'hexa' and shape is 'toroid', the map size along the first axis +% must be even. +% +% OPTIONAL INPUT ARGUMENTS +% +% argID (string) Argument identifier string (see below). +% value (varies) Value for the argument (see below). +% +% The optional arguments can be given as 'argID',value -pairs. If an +% argument is given value multiple times, the last one is +% used. The valid IDs and corresponding values are listed below. The values +% which are unambiguous (marked with '*') can be given without the +% preceeding argID. +% +% 'dlen' (scalar) length of the training data +% 'data' (matrix) the training data +% *(struct) the training data +% 'munits' (scalar) number of map units +% 'msize' (vector) map size +% 'lattice' *(string) map lattice: 'hexa' or 'rect' +% 'shape' *(string) map shape: 'sheet', 'cyl' or 'toroid' +% 'topol' *(struct) incomplete topology struct: its empty fields +% will be given values +% 'som_topol','sTopol' = 'topol' +% +% OUTPUT ARGUMENTS +% +% sT (struct) The topology struct. +% +% EXAMPLES +% +% The most important optional argument for the default topology is 'data'. +% To get a default topology (given data) use: +% +% sTopol = som_topol_struct('data',D); +% +% This sets lattice to its default value 'hexa'. If you want to have a +% 'rect' lattice instead: +% +% sTopol = som_topol_struct('data',D,'lattice','rect'); +% or +% sTopol = som_topol_struct('data',D,'rect'); +% +% If you want to have (close to) a specific number of map units, e.g. 100: +% +% sTopol = som_topol_struct('data',D,'munits',100); +% +% SEE ALSO +% +% som_make Initialize and train a map using default parameters. +% som_train_struct Default training parameters. +% som_randinint Random initialization algorithm. +% som_lininit Linear initialization algorithm. +% som_seqtrain Sequential training algorithm. +% som_batchtrain Batch training algorithm. + +% Copyright (c) 1999-2000 by the SOM toolbox programming team. +% http://www.cis.hut.fi/projects/somtoolbox/ + +% Version 2.0alpha juuso 060898 250399 070499 050899 240801 + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% check arguments + +% initialize +sTopol = som_set('som_topol','lattice','hexa','shape','sheet'); +D = []; +dlen = NaN; +dim = 2; +munits = NaN; + +% varargin +i=1; +while i<=length(varargin), + argok = 1; + if ischar(varargin{i}), + switch varargin{i}, + case 'dlen', i=i+1; dlen = varargin{i}; + case 'munits', i=i+1; munits = varargin{i}; sTopol.msize = 0; + case 'msize', i=i+1; sTopol.msize = varargin{i}; + case 'lattice', i=i+1; sTopol.lattice = varargin{i}; + case 'shape', i=i+1; sTopol.shape = varargin{i}; + case 'data', + i=i+1; + if isstruct(varargin{i}), D = varargin{i}.data; + else D = varargin{i}; + end + [dlen dim] = size(D); + case {'hexa','rect'}, sTopol.lattice = varargin{i}; + case {'sheet','cyl','toroid'}, sTopol.shape = varargin{i}; + case {'som_topol','sTopol','topol'}, + i=i+1; + if ~isempty(varargin{i}.msize) & prod(varargin{i}.msize), + sTopol.msize = varargin{i}.msize; + end + if ~isempty(varargin{i}.lattice), sTopol.lattice = varargin{i}.lattice; end + if ~isempty(varargin{i}.shape), sTopol.shape = varargin{i}.shape; end + otherwise argok=0; + end + elseif isstruct(varargin{i}) & isfield(varargin{i},'type'), + switch varargin{i}.type, + case 'som_topol', + if ~isempty(varargin{i}.msize) & prod(varargin{i}.msize), + sTopol.msize = varargin{i}.msize; + end + if ~isempty(varargin{i}.lattice), sTopol.lattice = varargin{i}.lattice; end + if ~isempty(varargin{i}.shape), sTopol.shape = varargin{i}.shape; end + case 'som_data', + D = varargin{i}.data; + [dlen dim] = size(D); + otherwise argok=0; + end + else + argok = 0; + end + if ~argok, + disp(['(som_topol_struct) Ignoring invalid argument #' num2str(i)]); + end + i = i+1; +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% action - topology struct + +% lattice and shape set already, so if msize is also set, there's +% nothing else to do +if prod(sTopol.msize) & ~isempty(sTopol.msize), return; end + +% otherwise, decide msize +% first (if necessary) determine the number of map units (munits) +if isnan(munits), + if ~isnan(dlen), + munits = ceil(5 * dlen^0.5); % this is just one way to make a guess... + else + munits = 100; % just a convenient value + end +end + +% then determine the map size (msize) +if dim == 1, % 1-D data + + sTopol.msize = [1 ceil(munits)]; + +elseif size(D,1)<2, % eigenvalues cannot be determined since there's no data + + sTopol.msize = round(sqrt(munits)); + sTopol.msize(2) = round(munits/sTopol.msize(1)); + +else % determine map size based on eigenvalues + + % initialize xdim/ydim ratio using principal components of the input + % space; the ratio is the square root of ratio of two largest eigenvalues + + % autocorrelation matrix + A = zeros(dim)+Inf; + for i=1:dim, D(:,i) = D(:,i) - mean(D(isfinite(D(:,i)),i)); end + for i=1:dim, + for j=i:dim, + c = D(:,i).*D(:,j); c = c(isfinite(c)); + A(i,j) = sum(c)/length(c); A(j,i) = A(i,j); + end + end + % take mdim first eigenvectors with the greatest eigenvalues + [V,S] = eig(A); + eigval = diag(S); + [y,ind] = sort(eigval); + eigval = eigval(ind); + + %me = mean(D); + %D = D - me(ones(length(ind),1),:); % remove mean from data + %eigval = sort(eig((D'*D)./size(D,1))); + if eigval(end)==0 | eigval(end-1)*munits<eigval(end), + ratio = 1; + else + ratio = sqrt(eigval(end)/eigval(end-1)); % ratio between map sidelengths + end + + % in hexagonal lattice, the sidelengths are not directly + % proportional to the number of units since the units on the + % y-axis are squeezed together by a factor of sqrt(0.75) + if strcmp(sTopol.lattice,'hexa'), + sTopol.msize(2) = min(munits, round(sqrt(munits / ratio * sqrt(0.75)))); + else + sTopol.msize(2) = min(munits, round(sqrt(munits / ratio))); + end + sTopol.msize(1) = round(munits / sTopol.msize(2)); + + % if actual dimension of the data is 1, make the map 1-D + if min(sTopol.msize) == 1, sTopol.msize = [1 max(sTopol.msize)]; end; + + % a special case: if the map is toroid with hexa lattice, + % size along first axis must be even + if strcmp(sTopol.lattice,'hexa') & strcmp(sTopol.shape,'toroid'), + if mod(sTopol.msize(1),2), sTopol.msize(1) = sTopol.msize(1) + 1; end + end + +end + +return; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%