annotate toolboxes/MIRtoolbox1.3.2/somtoolbox/som_topol_struct.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 sTopol = som_topol_struct(varargin)
Daniel@0 2
Daniel@0 3 %SOM_TOPOL_STRUCT Default values for SOM topology.
Daniel@0 4 %
Daniel@0 5 % sT = som_topol_struct([[argID,] value, ...])
Daniel@0 6 %
Daniel@0 7 % sTopol = som_topol_struct('data',D);
Daniel@0 8 % sTopol = som_topol_struct('data',D,'munits',200);
Daniel@0 9 % sTopol = som_topol_struct(sTopol);
Daniel@0 10 % sTopol = som_topol_struct;
Daniel@0 11 %
Daniel@0 12 % Input and output arguments ([]'s are optional):
Daniel@0 13 % [argID, (string) Default map topology depends on a number of
Daniel@0 14 % value] (varies) factors (see below). These are given as a
Daniel@0 15 % argument ID - argument value pairs, listed below.
Daniel@0 16 %
Daniel@0 17 % sT (struct) The ready topology struct.
Daniel@0 18 %
Daniel@0 19 % Topology struct contains values for map size, lattice (default is 'hexa')
Daniel@0 20 % and shape (default is 'sheet'). Map size depends on training data and the
Daniel@0 21 % number of map units. The number of map units depends on number of training
Daniel@0 22 % samples.
Daniel@0 23 %
Daniel@0 24 % Here are the valid argument IDs and corresponding values. The values which
Daniel@0 25 % are unambiguous (marked with '*') can be given without the preceeding argID.
Daniel@0 26 % 'dlen' (scalar) length of the training data
Daniel@0 27 % 'data' (matrix) the training data
Daniel@0 28 % *(struct) the training data
Daniel@0 29 % 'munits' (scalar) number of map units
Daniel@0 30 % 'msize' (vector) map size
Daniel@0 31 % 'lattice' *(string) map lattice: 'hexa' or 'rect'
Daniel@0 32 % 'shape' *(string) map shape: 'sheet', 'cyl' or 'toroid'
Daniel@0 33 % 'topol' *(struct) incomplete topology struct: its empty fields
Daniel@0 34 % will be given values
Daniel@0 35 % 'som_topol','sTopol' = 'topol'
Daniel@0 36 %
Daniel@0 37 % For more help, try 'type som_topol_struct' or check out online documentation.
Daniel@0 38 % See also SOM_SET, SOM_TRAIN_STRUCT, SOM_MAKE.
Daniel@0 39
Daniel@0 40 %%%%%%%%%%%%% DETAILED DESCRIPTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Daniel@0 41 %
Daniel@0 42 % som_topol_struct
Daniel@0 43 %
Daniel@0 44 % PURPOSE
Daniel@0 45 %
Daniel@0 46 % Default values for map topology and training parameters.
Daniel@0 47 %
Daniel@0 48 % SYNTAX
Daniel@0 49 %
Daniel@0 50 % sT = som_topol_struct('argID',value,...);
Daniel@0 51 % sT = som_topol_struct(value,...);
Daniel@0 52 %
Daniel@0 53 % DESCRIPTION
Daniel@0 54 %
Daniel@0 55 % This function is used to give sensible values for map topology (ie. map
Daniel@0 56 % size). The topology struct is returned.
Daniel@0 57 %
Daniel@0 58 % The topology struct has three fields: '.msize', '.lattice' and
Daniel@0 59 % '.shape'. Of these, default value for '.lattice' is 'hexa' and for
Daniel@0 60 % '.shape' 'sheet'. Only the '.msize' field depends on the optional
Daniel@0 61 % arguments: 'dlen', 'munits' and 'data'. The value for '.msize' field is
Daniel@0 62 % determined as follows.
Daniel@0 63 %
Daniel@0 64 % First, the number of map units is determined (unless it is given). A
Daniel@0 65 % heuristic formula of 'munits = 5*sqrt(dlen)' is used to calculate
Daniel@0 66 % it. After this, the map size is determined. Basically, the two biggest
Daniel@0 67 % eigenvalues of the training data are calculated and the ratio between
Daniel@0 68 % sidelengths of the map grid is set to the square root of this ratio. The
Daniel@0 69 % actual sidelengths are then set so that their product is as close to the
Daniel@0 70 % desired number of map units as possible. If the lattice of the grid is
Daniel@0 71 % 'hexa', the ratio is modified a bit to take it into account. If the
Daniel@0 72 % lattice is 'hexa' and shape is 'toroid', the map size along the first axis
Daniel@0 73 % must be even.
Daniel@0 74 %
Daniel@0 75 % OPTIONAL INPUT ARGUMENTS
Daniel@0 76 %
Daniel@0 77 % argID (string) Argument identifier string (see below).
Daniel@0 78 % value (varies) Value for the argument (see below).
Daniel@0 79 %
Daniel@0 80 % The optional arguments can be given as 'argID',value -pairs. If an
Daniel@0 81 % argument is given value multiple times, the last one is
Daniel@0 82 % used. The valid IDs and corresponding values are listed below. The values
Daniel@0 83 % which are unambiguous (marked with '*') can be given without the
Daniel@0 84 % preceeding argID.
Daniel@0 85 %
Daniel@0 86 % 'dlen' (scalar) length of the training data
Daniel@0 87 % 'data' (matrix) the training data
Daniel@0 88 % *(struct) the training data
Daniel@0 89 % 'munits' (scalar) number of map units
Daniel@0 90 % 'msize' (vector) map size
Daniel@0 91 % 'lattice' *(string) map lattice: 'hexa' or 'rect'
Daniel@0 92 % 'shape' *(string) map shape: 'sheet', 'cyl' or 'toroid'
Daniel@0 93 % 'topol' *(struct) incomplete topology struct: its empty fields
Daniel@0 94 % will be given values
Daniel@0 95 % 'som_topol','sTopol' = 'topol'
Daniel@0 96 %
Daniel@0 97 % OUTPUT ARGUMENTS
Daniel@0 98 %
Daniel@0 99 % sT (struct) The topology struct.
Daniel@0 100 %
Daniel@0 101 % EXAMPLES
Daniel@0 102 %
Daniel@0 103 % The most important optional argument for the default topology is 'data'.
Daniel@0 104 % To get a default topology (given data) use:
Daniel@0 105 %
Daniel@0 106 % sTopol = som_topol_struct('data',D);
Daniel@0 107 %
Daniel@0 108 % This sets lattice to its default value 'hexa'. If you want to have a
Daniel@0 109 % 'rect' lattice instead:
Daniel@0 110 %
Daniel@0 111 % sTopol = som_topol_struct('data',D,'lattice','rect');
Daniel@0 112 % or
Daniel@0 113 % sTopol = som_topol_struct('data',D,'rect');
Daniel@0 114 %
Daniel@0 115 % If you want to have (close to) a specific number of map units, e.g. 100:
Daniel@0 116 %
Daniel@0 117 % sTopol = som_topol_struct('data',D,'munits',100);
Daniel@0 118 %
Daniel@0 119 % SEE ALSO
Daniel@0 120 %
Daniel@0 121 % som_make Initialize and train a map using default parameters.
Daniel@0 122 % som_train_struct Default training parameters.
Daniel@0 123 % som_randinint Random initialization algorithm.
Daniel@0 124 % som_lininit Linear initialization algorithm.
Daniel@0 125 % som_seqtrain Sequential training algorithm.
Daniel@0 126 % som_batchtrain Batch training algorithm.
Daniel@0 127
Daniel@0 128 % Copyright (c) 1999-2000 by the SOM toolbox programming team.
Daniel@0 129 % http://www.cis.hut.fi/projects/somtoolbox/
Daniel@0 130
Daniel@0 131 % Version 2.0alpha juuso 060898 250399 070499 050899 240801
Daniel@0 132
Daniel@0 133 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Daniel@0 134 %% check arguments
Daniel@0 135
Daniel@0 136 % initialize
Daniel@0 137 sTopol = som_set('som_topol','lattice','hexa','shape','sheet');
Daniel@0 138 D = [];
Daniel@0 139 dlen = NaN;
Daniel@0 140 dim = 2;
Daniel@0 141 munits = NaN;
Daniel@0 142
Daniel@0 143 % varargin
Daniel@0 144 i=1;
Daniel@0 145 while i<=length(varargin),
Daniel@0 146 argok = 1;
Daniel@0 147 if ischar(varargin{i}),
Daniel@0 148 switch varargin{i},
Daniel@0 149 case 'dlen', i=i+1; dlen = varargin{i};
Daniel@0 150 case 'munits', i=i+1; munits = varargin{i}; sTopol.msize = 0;
Daniel@0 151 case 'msize', i=i+1; sTopol.msize = varargin{i};
Daniel@0 152 case 'lattice', i=i+1; sTopol.lattice = varargin{i};
Daniel@0 153 case 'shape', i=i+1; sTopol.shape = varargin{i};
Daniel@0 154 case 'data',
Daniel@0 155 i=i+1;
Daniel@0 156 if isstruct(varargin{i}), D = varargin{i}.data;
Daniel@0 157 else D = varargin{i};
Daniel@0 158 end
Daniel@0 159 [dlen dim] = size(D);
Daniel@0 160 case {'hexa','rect'}, sTopol.lattice = varargin{i};
Daniel@0 161 case {'sheet','cyl','toroid'}, sTopol.shape = varargin{i};
Daniel@0 162 case {'som_topol','sTopol','topol'},
Daniel@0 163 i=i+1;
Daniel@0 164 if ~isempty(varargin{i}.msize) & prod(varargin{i}.msize),
Daniel@0 165 sTopol.msize = varargin{i}.msize;
Daniel@0 166 end
Daniel@0 167 if ~isempty(varargin{i}.lattice), sTopol.lattice = varargin{i}.lattice; end
Daniel@0 168 if ~isempty(varargin{i}.shape), sTopol.shape = varargin{i}.shape; end
Daniel@0 169 otherwise argok=0;
Daniel@0 170 end
Daniel@0 171 elseif isstruct(varargin{i}) & isfield(varargin{i},'type'),
Daniel@0 172 switch varargin{i}.type,
Daniel@0 173 case 'som_topol',
Daniel@0 174 if ~isempty(varargin{i}.msize) & prod(varargin{i}.msize),
Daniel@0 175 sTopol.msize = varargin{i}.msize;
Daniel@0 176 end
Daniel@0 177 if ~isempty(varargin{i}.lattice), sTopol.lattice = varargin{i}.lattice; end
Daniel@0 178 if ~isempty(varargin{i}.shape), sTopol.shape = varargin{i}.shape; end
Daniel@0 179 case 'som_data',
Daniel@0 180 D = varargin{i}.data;
Daniel@0 181 [dlen dim] = size(D);
Daniel@0 182 otherwise argok=0;
Daniel@0 183 end
Daniel@0 184 else
Daniel@0 185 argok = 0;
Daniel@0 186 end
Daniel@0 187 if ~argok,
Daniel@0 188 disp(['(som_topol_struct) Ignoring invalid argument #' num2str(i)]);
Daniel@0 189 end
Daniel@0 190 i = i+1;
Daniel@0 191 end
Daniel@0 192
Daniel@0 193 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Daniel@0 194 %% action - topology struct
Daniel@0 195
Daniel@0 196 % lattice and shape set already, so if msize is also set, there's
Daniel@0 197 % nothing else to do
Daniel@0 198 if prod(sTopol.msize) & ~isempty(sTopol.msize), return; end
Daniel@0 199
Daniel@0 200 % otherwise, decide msize
Daniel@0 201 % first (if necessary) determine the number of map units (munits)
Daniel@0 202 if isnan(munits),
Daniel@0 203 if ~isnan(dlen),
Daniel@0 204 munits = ceil(5 * dlen^0.5); % this is just one way to make a guess...
Daniel@0 205 else
Daniel@0 206 munits = 100; % just a convenient value
Daniel@0 207 end
Daniel@0 208 end
Daniel@0 209
Daniel@0 210 % then determine the map size (msize)
Daniel@0 211 if dim == 1, % 1-D data
Daniel@0 212
Daniel@0 213 sTopol.msize = [1 ceil(munits)];
Daniel@0 214
Daniel@0 215 elseif size(D,1)<2, % eigenvalues cannot be determined since there's no data
Daniel@0 216
Daniel@0 217 sTopol.msize = round(sqrt(munits));
Daniel@0 218 sTopol.msize(2) = round(munits/sTopol.msize(1));
Daniel@0 219
Daniel@0 220 else % determine map size based on eigenvalues
Daniel@0 221
Daniel@0 222 % initialize xdim/ydim ratio using principal components of the input
Daniel@0 223 % space; the ratio is the square root of ratio of two largest eigenvalues
Daniel@0 224
Daniel@0 225 % autocorrelation matrix
Daniel@0 226 A = zeros(dim)+Inf;
Daniel@0 227 for i=1:dim, D(:,i) = D(:,i) - mean(D(isfinite(D(:,i)),i)); end
Daniel@0 228 for i=1:dim,
Daniel@0 229 for j=i:dim,
Daniel@0 230 c = D(:,i).*D(:,j); c = c(isfinite(c));
Daniel@0 231 A(i,j) = sum(c)/length(c); A(j,i) = A(i,j);
Daniel@0 232 end
Daniel@0 233 end
Daniel@0 234 % take mdim first eigenvectors with the greatest eigenvalues
Daniel@0 235 [V,S] = eig(A);
Daniel@0 236 eigval = diag(S);
Daniel@0 237 [y,ind] = sort(eigval);
Daniel@0 238 eigval = eigval(ind);
Daniel@0 239
Daniel@0 240 %me = mean(D);
Daniel@0 241 %D = D - me(ones(length(ind),1),:); % remove mean from data
Daniel@0 242 %eigval = sort(eig((D'*D)./size(D,1)));
Daniel@0 243 if eigval(end)==0 | eigval(end-1)*munits<eigval(end),
Daniel@0 244 ratio = 1;
Daniel@0 245 else
Daniel@0 246 ratio = sqrt(eigval(end)/eigval(end-1)); % ratio between map sidelengths
Daniel@0 247 end
Daniel@0 248
Daniel@0 249 % in hexagonal lattice, the sidelengths are not directly
Daniel@0 250 % proportional to the number of units since the units on the
Daniel@0 251 % y-axis are squeezed together by a factor of sqrt(0.75)
Daniel@0 252 if strcmp(sTopol.lattice,'hexa'),
Daniel@0 253 sTopol.msize(2) = min(munits, round(sqrt(munits / ratio * sqrt(0.75))));
Daniel@0 254 else
Daniel@0 255 sTopol.msize(2) = min(munits, round(sqrt(munits / ratio)));
Daniel@0 256 end
Daniel@0 257 sTopol.msize(1) = round(munits / sTopol.msize(2));
Daniel@0 258
Daniel@0 259 % if actual dimension of the data is 1, make the map 1-D
Daniel@0 260 if min(sTopol.msize) == 1, sTopol.msize = [1 max(sTopol.msize)]; end;
Daniel@0 261
Daniel@0 262 % a special case: if the map is toroid with hexa lattice,
Daniel@0 263 % size along first axis must be even
Daniel@0 264 if strcmp(sTopol.lattice,'hexa') & strcmp(sTopol.shape,'toroid'),
Daniel@0 265 if mod(sTopol.msize(1),2), sTopol.msize(1) = sTopol.msize(1) + 1; end
Daniel@0 266 end
Daniel@0 267
Daniel@0 268 end
Daniel@0 269
Daniel@0 270 return;
Daniel@0 271
Daniel@0 272 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%