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