wolffd@0
|
1 function [sMap, sTrain] = som_seqtrain(sMap, D, varargin)
|
wolffd@0
|
2
|
wolffd@0
|
3 %SOM_SEQTRAIN Use sequential algorithm to train the Self-Organizing Map.
|
wolffd@0
|
4 %
|
wolffd@0
|
5 % [sM,sT] = som_seqtrain(sM, D, [[argID,] value, ...])
|
wolffd@0
|
6 %
|
wolffd@0
|
7 % sM = som_seqtrain(sM,D);
|
wolffd@0
|
8 % sM = som_seqtrain(sM,sD,'alpha_type','power','tracking',3);
|
wolffd@0
|
9 % [M,sT] = som_seqtrain(M,D,'ep','trainlen',10,'inv','hexa');
|
wolffd@0
|
10 %
|
wolffd@0
|
11 % Input and output arguments ([]'s are optional):
|
wolffd@0
|
12 % sM (struct) map struct, the trained and updated map is returned
|
wolffd@0
|
13 % (matrix) codebook matrix of a self-organizing map
|
wolffd@0
|
14 % size munits x dim or msize(1) x ... x msize(k) x dim
|
wolffd@0
|
15 % The trained map codebook is returned.
|
wolffd@0
|
16 % D (struct) training data; data struct
|
wolffd@0
|
17 % (matrix) training data, size dlen x dim
|
wolffd@0
|
18 % [argID, (string) See below. The values which are unambiguous can
|
wolffd@0
|
19 % value] (varies) be given without the preceeding argID.
|
wolffd@0
|
20 %
|
wolffd@0
|
21 % sT (struct) learning parameters used during the training
|
wolffd@0
|
22 %
|
wolffd@0
|
23 % Here are the valid argument IDs and corresponding values. The values which
|
wolffd@0
|
24 % are unambiguous (marked with '*') can be given without the preceeding argID.
|
wolffd@0
|
25 % 'mask' (vector) BMU search mask, size dim x 1
|
wolffd@0
|
26 % 'msize' (vector) map size
|
wolffd@0
|
27 % 'radius' (vector) neighborhood radiuses, length 1, 2 or trainlen
|
wolffd@0
|
28 % 'radius_ini' (scalar) initial training radius
|
wolffd@0
|
29 % 'radius_fin' (scalar) final training radius
|
wolffd@0
|
30 % 'alpha' (vector) learning rates, length trainlen
|
wolffd@0
|
31 % 'alpha_ini' (scalar) initial learning rate
|
wolffd@0
|
32 % 'tracking' (scalar) tracking level, 0-3
|
wolffd@0
|
33 % 'trainlen' (scalar) training length
|
wolffd@0
|
34 % 'trainlen_type' *(string) is the given trainlen 'samples' or 'epochs'
|
wolffd@0
|
35 % 'train' *(struct) train struct, parameters for training
|
wolffd@0
|
36 % 'sTrain','som_train ' = 'train'
|
wolffd@0
|
37 % 'alpha_type' *(string) learning rate function, 'inv', 'linear' or 'power'
|
wolffd@0
|
38 % 'sample_order'*(string) order of samples: 'random' or 'ordered'
|
wolffd@0
|
39 % 'neigh' *(string) neighborhood function, 'gaussian', 'cutgauss',
|
wolffd@0
|
40 % 'ep' or 'bubble'
|
wolffd@0
|
41 % 'topol' *(struct) topology struct
|
wolffd@0
|
42 % 'som_topol','sTopo l' = 'topol'
|
wolffd@0
|
43 % 'lattice' *(string) map lattice, 'hexa' or 'rect'
|
wolffd@0
|
44 % 'shape' *(string) map shape, 'sheet', 'cyl' or 'toroid'
|
wolffd@0
|
45 %
|
wolffd@0
|
46 % For more help, try 'type som_seqtrain' or check out online documentation.
|
wolffd@0
|
47 % See also SOM_MAKE, SOM_BATCHTRAIN, SOM_TRAIN_STRUCT.
|
wolffd@0
|
48
|
wolffd@0
|
49 %%%%%%%%%%%%% DETAILED DESCRIPTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
wolffd@0
|
50 %
|
wolffd@0
|
51 % som_seqtrain
|
wolffd@0
|
52 %
|
wolffd@0
|
53 % PURPOSE
|
wolffd@0
|
54 %
|
wolffd@0
|
55 % Trains a Self-Organizing Map using the sequential algorithm.
|
wolffd@0
|
56 %
|
wolffd@0
|
57 % SYNTAX
|
wolffd@0
|
58 %
|
wolffd@0
|
59 % sM = som_seqtrain(sM,D);
|
wolffd@0
|
60 % sM = som_seqtrain(sM,sD);
|
wolffd@0
|
61 % sM = som_seqtrain(...,'argID',value,...);
|
wolffd@0
|
62 % sM = som_seqtrain(...,value,...);
|
wolffd@0
|
63 % [sM,sT] = som_seqtrain(M,D,...);
|
wolffd@0
|
64 %
|
wolffd@0
|
65 % DESCRIPTION
|
wolffd@0
|
66 %
|
wolffd@0
|
67 % Trains the given SOM (sM or M above) with the given training data
|
wolffd@0
|
68 % (sD or D) using sequential SOM training algorithm. If no optional
|
wolffd@0
|
69 % arguments (argID, value) are given, a default training is done, the
|
wolffd@0
|
70 % parameters are obtained from SOM_TRAIN_STRUCT function. Using
|
wolffd@0
|
71 % optional arguments the training parameters can be specified. Returns
|
wolffd@0
|
72 % the trained and updated SOM and a train struct which contains
|
wolffd@0
|
73 % information on the training.
|
wolffd@0
|
74 %
|
wolffd@0
|
75 % REFERENCES
|
wolffd@0
|
76 %
|
wolffd@0
|
77 % Kohonen, T., "Self-Organizing Map", 2nd ed., Springer-Verlag,
|
wolffd@0
|
78 % Berlin, 1995, pp. 78-82.
|
wolffd@0
|
79 % Kohonen, T., "Clustering, Taxonomy, and Topological Maps of
|
wolffd@0
|
80 % Patterns", International Conference on Pattern Recognition
|
wolffd@0
|
81 % (ICPR), 1982, pp. 114-128.
|
wolffd@0
|
82 % Kohonen, T., "Self-Organized formation of topologically correct
|
wolffd@0
|
83 % feature maps", Biological Cybernetics 43, 1982, pp. 59-69.
|
wolffd@0
|
84 %
|
wolffd@0
|
85 % REQUIRED INPUT ARGUMENTS
|
wolffd@0
|
86 %
|
wolffd@0
|
87 % sM The map to be trained.
|
wolffd@0
|
88 % (struct) map struct
|
wolffd@0
|
89 % (matrix) codebook matrix (field .data of map struct)
|
wolffd@0
|
90 % Size is either [munits dim], in which case the map grid
|
wolffd@0
|
91 % dimensions (msize) should be specified with optional arguments,
|
wolffd@0
|
92 % or [msize(1) ... msize(k) dim] in which case the map
|
wolffd@0
|
93 % grid dimensions are taken from the size of the matrix.
|
wolffd@0
|
94 % Lattice, by default, is 'rect' and shape 'sheet'.
|
wolffd@0
|
95 % D Training data.
|
wolffd@0
|
96 % (struct) data struct
|
wolffd@0
|
97 % (matrix) data matrix, size [dlen dim]
|
wolffd@0
|
98 %
|
wolffd@0
|
99 % OPTIONAL INPUT ARGUMENTS
|
wolffd@0
|
100 %
|
wolffd@0
|
101 % argID (string) Argument identifier string (see below).
|
wolffd@0
|
102 % value (varies) Value for the argument (see below).
|
wolffd@0
|
103 %
|
wolffd@0
|
104 % The optional arguments can be given as 'argID',value -pairs. If an
|
wolffd@0
|
105 % argument is given value multiple times, the last one is
|
wolffd@0
|
106 % used. The valid IDs and corresponding values are listed below. The values
|
wolffd@0
|
107 % which are unambiguous (marked with '*') can be given without the
|
wolffd@0
|
108 % preceeding argID.
|
wolffd@0
|
109 %
|
wolffd@0
|
110 % 'mask' (vector) BMU search mask, size dim x 1. Default is
|
wolffd@0
|
111 % the one in sM (field '.mask') or a vector of
|
wolffd@0
|
112 % ones if only a codebook matrix was given.
|
wolffd@0
|
113 % 'msize' (vector) map grid dimensions. Default is the one
|
wolffd@0
|
114 % in sM (field sM.topol.msize) or
|
wolffd@0
|
115 % 'si = size(sM); msize = si(1:end-1);'
|
wolffd@0
|
116 % if only a codebook matrix was given.
|
wolffd@0
|
117 % 'radius' (vector) neighborhood radius
|
wolffd@0
|
118 % length = 1: radius_ini = radius
|
wolffd@0
|
119 % length = 2: [radius_ini radius_fin] = radius
|
wolffd@0
|
120 % length > 2: the vector given neighborhood
|
wolffd@0
|
121 % radius for each step separately
|
wolffd@0
|
122 % trainlen = length(radius)
|
wolffd@0
|
123 % 'radius_ini' (scalar) initial training radius
|
wolffd@0
|
124 % 'radius_fin' (scalar) final training radius
|
wolffd@0
|
125 % 'alpha' (vector) learning rate
|
wolffd@0
|
126 % length = 1: alpha_ini = alpha
|
wolffd@0
|
127 % length > 1: the vector gives learning rate
|
wolffd@0
|
128 % for each step separately
|
wolffd@0
|
129 % trainlen is set to length(alpha)
|
wolffd@0
|
130 % alpha_type is set to 'user defined'
|
wolffd@0
|
131 % 'alpha_ini' (scalar) initial learning rate
|
wolffd@0
|
132 % 'tracking' (scalar) tracking level: 0, 1 (default), 2 or 3
|
wolffd@0
|
133 % 0 - estimate time
|
wolffd@0
|
134 % 1 - track time and quantization error
|
wolffd@0
|
135 % 2 - plot quantization error
|
wolffd@0
|
136 % 3 - plot quantization error and two first
|
wolffd@0
|
137 % components
|
wolffd@0
|
138 % 'trainlen' (scalar) training length (see also 'tlen_type')
|
wolffd@0
|
139 % 'trainlen_type' *(string) is the trainlen argument given in 'epochs'
|
wolffd@0
|
140 % or in 'samples'. Default is 'epochs'.
|
wolffd@0
|
141 % 'sample_order'*(string) is the sample order 'random' (which is the
|
wolffd@0
|
142 % the default) or 'ordered' in which case
|
wolffd@0
|
143 % samples are taken in the order in which they
|
wolffd@0
|
144 % appear in the data set
|
wolffd@0
|
145 % 'train' *(struct) train struct, parameters for training.
|
wolffd@0
|
146 % Default parameters, unless specified,
|
wolffd@0
|
147 % are acquired using SOM_TRAIN_STRUCT (this
|
wolffd@0
|
148 % also applies for 'trainlen', 'alpha_type',
|
wolffd@0
|
149 % 'alpha_ini', 'radius_ini' and 'radius_fin').
|
wolffd@0
|
150 % 'sTrain', 'som_train' (struct) = 'train'
|
wolffd@0
|
151 % 'neigh' *(string) The used neighborhood function. Default is
|
wolffd@0
|
152 % the one in sM (field '.neigh') or 'gaussian'
|
wolffd@0
|
153 % if only a codebook matrix was given. Other
|
wolffd@0
|
154 % possible values is 'cutgauss', 'ep' and 'bubble'.
|
wolffd@0
|
155 % 'topol' *(struct) topology of the map. Default is the one
|
wolffd@0
|
156 % in sM (field '.topol').
|
wolffd@0
|
157 % 'sTopol', 'som_topol' (struct) = 'topol'
|
wolffd@0
|
158 % 'alpha_type'*(string) learning rate function, 'inv', 'linear' or 'power'
|
wolffd@0
|
159 % 'lattice' *(string) map lattice. Default is the one in sM
|
wolffd@0
|
160 % (field sM.topol.lattice) or 'rect'
|
wolffd@0
|
161 % if only a codebook matrix was given.
|
wolffd@0
|
162 % 'shape' *(string) map shape. Default is the one in sM
|
wolffd@0
|
163 % (field sM.topol.shape) or 'sheet'
|
wolffd@0
|
164 % if only a codebook matrix was given.
|
wolffd@0
|
165 %
|
wolffd@0
|
166 % OUTPUT ARGUMENTS
|
wolffd@0
|
167 %
|
wolffd@0
|
168 % sM the trained map
|
wolffd@0
|
169 % (struct) if a map struct was given as input argument, a
|
wolffd@0
|
170 % map struct is also returned. The current training
|
wolffd@0
|
171 % is added to the training history (sM.trainhist).
|
wolffd@0
|
172 % The 'neigh' and 'mask' fields of the map struct
|
wolffd@0
|
173 % are updated to match those of the training.
|
wolffd@0
|
174 % (matrix) if a matrix was given as input argument, a matrix
|
wolffd@0
|
175 % is also returned with the same size as the input
|
wolffd@0
|
176 % argument.
|
wolffd@0
|
177 % sT (struct) train struct; information of the accomplished training
|
wolffd@0
|
178 %
|
wolffd@0
|
179 % EXAMPLES
|
wolffd@0
|
180 %
|
wolffd@0
|
181 % Simplest case:
|
wolffd@0
|
182 % sM = som_seqtrain(sM,D);
|
wolffd@0
|
183 % sM = som_seqtrain(sM,sD);
|
wolffd@0
|
184 %
|
wolffd@0
|
185 % To change the tracking level, 'tracking' argument is specified:
|
wolffd@0
|
186 % sM = som_seqtrain(sM,D,'tracking',3);
|
wolffd@0
|
187 %
|
wolffd@0
|
188 % The change training parameters, the optional arguments 'train',
|
wolffd@0
|
189 % 'neigh','mask','trainlen','radius','radius_ini', 'radius_fin',
|
wolffd@0
|
190 % 'alpha', 'alpha_type' and 'alpha_ini' are used.
|
wolffd@0
|
191 % sM = som_seqtrain(sM,D,'neigh','cutgauss','trainlen',10,'radius_fin',0);
|
wolffd@0
|
192 %
|
wolffd@0
|
193 % Another way to specify training parameters is to create a train struct:
|
wolffd@0
|
194 % sTrain = som_train_struct(sM,'dlen',size(D,1),'algorithm','seq');
|
wolffd@0
|
195 % sTrain = som_set(sTrain,'neigh','cutgauss');
|
wolffd@0
|
196 % sM = som_seqtrain(sM,D,sTrain);
|
wolffd@0
|
197 %
|
wolffd@0
|
198 % By default the neighborhood radius goes linearly from radius_ini to
|
wolffd@0
|
199 % radius_fin. If you want to change this, you can use the 'radius' argument
|
wolffd@0
|
200 % to specify the neighborhood radius for each step separately:
|
wolffd@0
|
201 % sM = som_seqtrain(sM,D,'radius',[5 3 1 1 1 1 0.5 0.5 0.5]);
|
wolffd@0
|
202 %
|
wolffd@0
|
203 % By default the learning rate (alpha) goes from the alpha_ini to 0
|
wolffd@0
|
204 % along the function defined by alpha_type. If you want to change this,
|
wolffd@0
|
205 % you can use the 'alpha' argument to specify the learning rate
|
wolffd@0
|
206 % for each step separately:
|
wolffd@0
|
207 % alpha = 0.2*(1 - log([1:100]));
|
wolffd@0
|
208 % sM = som_seqtrain(sM,D,'alpha',alpha);
|
wolffd@0
|
209 %
|
wolffd@0
|
210 % You don't necessarily have to use the map struct, but you can operate
|
wolffd@0
|
211 % directly with codebook matrices. However, in this case you have to
|
wolffd@0
|
212 % specify the topology of the map in the optional arguments. The
|
wolffd@0
|
213 % following commads are identical (M is originally a 200 x dim sized matrix):
|
wolffd@0
|
214 % M = som_seqtrain(M,D,'msize',[20 10],'lattice','hexa','shape','cyl');
|
wolffd@0
|
215 %
|
wolffd@0
|
216 % M = som_seqtrain(M,D,'msize',[20 10],'hexa','cyl');
|
wolffd@0
|
217 %
|
wolffd@0
|
218 % sT= som_set('som_topol','msize',[20 10],'lattice','hexa','shape','cyl');
|
wolffd@0
|
219 % M = som_seqtrain(M,D,sT);
|
wolffd@0
|
220 %
|
wolffd@0
|
221 % M = reshape(M,[20 10 dim]);
|
wolffd@0
|
222 % M = som_seqtrain(M,D,'hexa','cyl');
|
wolffd@0
|
223 %
|
wolffd@0
|
224 % The som_seqtrain also returns a train struct with information on the
|
wolffd@0
|
225 % accomplished training. This is the same one as is added to the end of the
|
wolffd@0
|
226 % trainhist field of map struct, in case a map struct is given.
|
wolffd@0
|
227 % [M,sTrain] = som_seqtrain(M,D,'msize',[20 10]);
|
wolffd@0
|
228 %
|
wolffd@0
|
229 % [sM,sTrain] = som_seqtrain(sM,D); % sM.trainhist{end}==sTrain
|
wolffd@0
|
230 %
|
wolffd@0
|
231 % SEE ALSO
|
wolffd@0
|
232 %
|
wolffd@0
|
233 % som_make Initialize and train a SOM using default parameters.
|
wolffd@0
|
234 % som_batchtrain Train SOM with batch algorithm.
|
wolffd@0
|
235 % som_train_struct Determine default training parameters.
|
wolffd@0
|
236
|
wolffd@0
|
237 % Copyright (c) 1997-2000 by the SOM toolbox programming team.
|
wolffd@0
|
238 % http://www.cis.hut.fi/projects/somtoolbox/
|
wolffd@0
|
239
|
wolffd@0
|
240 % Version 1.0beta juuso 220997
|
wolffd@0
|
241 % Version 2.0beta juuso 101199
|
wolffd@0
|
242
|
wolffd@0
|
243 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
wolffd@0
|
244 %% Check arguments
|
wolffd@0
|
245
|
wolffd@0
|
246 error(nargchk(2, Inf, nargin)); % check the number of input arguments
|
wolffd@0
|
247
|
wolffd@0
|
248 % map
|
wolffd@0
|
249 struct_mode = isstruct(sMap);
|
wolffd@0
|
250 if struct_mode,
|
wolffd@0
|
251 sTopol = sMap.topol;
|
wolffd@0
|
252 else
|
wolffd@0
|
253 orig_size = size(sMap);
|
wolffd@0
|
254 if ndims(sMap) > 2,
|
wolffd@0
|
255 si = size(sMap); dim = si(end); msize = si(1:end-1);
|
wolffd@0
|
256 M = reshape(sMap,[prod(msize) dim]);
|
wolffd@0
|
257 else
|
wolffd@0
|
258 msize = [orig_size(1) 1];
|
wolffd@0
|
259 dim = orig_size(2);
|
wolffd@0
|
260 end
|
wolffd@0
|
261 sMap = som_map_struct(dim,'msize',msize);
|
wolffd@0
|
262 sTopol = sMap.topol;
|
wolffd@0
|
263 end
|
wolffd@0
|
264 [munits dim] = size(sMap.codebook);
|
wolffd@0
|
265
|
wolffd@0
|
266 % data
|
wolffd@0
|
267 if isstruct(D),
|
wolffd@0
|
268 data_name = D.name;
|
wolffd@0
|
269 D = D.data;
|
wolffd@0
|
270 else
|
wolffd@0
|
271 data_name = inputname(2);
|
wolffd@0
|
272 end
|
wolffd@0
|
273 D = D(find(sum(isnan(D),2) < dim),:); % remove empty vectors from the data
|
wolffd@0
|
274 [dlen ddim] = size(D); % check input dimension
|
wolffd@0
|
275 if dim ~= ddim, error('Map and data input space dimensions disagree.'); end
|
wolffd@0
|
276
|
wolffd@0
|
277 % varargin
|
wolffd@0
|
278 sTrain = som_set('som_train','algorithm','seq','neigh', ...
|
wolffd@0
|
279 sMap.neigh,'mask',sMap.mask,'data_name',data_name);
|
wolffd@0
|
280 radius = [];
|
wolffd@0
|
281 alpha = [];
|
wolffd@0
|
282 tracking = 1;
|
wolffd@0
|
283 sample_order_type = 'random';
|
wolffd@0
|
284 tlen_type = 'epochs';
|
wolffd@0
|
285
|
wolffd@0
|
286 i=1;
|
wolffd@0
|
287 while i<=length(varargin),
|
wolffd@0
|
288 argok = 1;
|
wolffd@0
|
289 if ischar(varargin{i}),
|
wolffd@0
|
290 switch varargin{i},
|
wolffd@0
|
291 % argument IDs
|
wolffd@0
|
292 case 'msize', i=i+1; sTopol.msize = varargin{i};
|
wolffd@0
|
293 case 'lattice', i=i+1; sTopol.lattice = varargin{i};
|
wolffd@0
|
294 case 'shape', i=i+1; sTopol.shape = varargin{i};
|
wolffd@0
|
295 case 'mask', i=i+1; sTrain.mask = varargin{i};
|
wolffd@0
|
296 case 'neigh', i=i+1; sTrain.neigh = varargin{i};
|
wolffd@0
|
297 case 'trainlen', i=i+1; sTrain.trainlen = varargin{i};
|
wolffd@0
|
298 case 'trainlen_type', i=i+1; tlen_type = varargin{i};
|
wolffd@0
|
299 case 'tracking', i=i+1; tracking = varargin{i};
|
wolffd@0
|
300 case 'sample_order', i=i+1; sample_order_type = varargin{i};
|
wolffd@0
|
301 case 'radius_ini', i=i+1; sTrain.radius_ini = varargin{i};
|
wolffd@0
|
302 case 'radius_fin', i=i+1; sTrain.radius_fin = varargin{i};
|
wolffd@0
|
303 case 'radius',
|
wolffd@0
|
304 i=i+1;
|
wolffd@0
|
305 l = length(varargin{i});
|
wolffd@0
|
306 if l==1,
|
wolffd@0
|
307 sTrain.radius_ini = varargin{i};
|
wolffd@0
|
308 else
|
wolffd@0
|
309 sTrain.radius_ini = varargin{i}(1);
|
wolffd@0
|
310 sTrain.radius_fin = varargin{i}(end);
|
wolffd@0
|
311 if l>2, radius = varargin{i}; tlen_type = 'samples'; end
|
wolffd@0
|
312 end
|
wolffd@0
|
313 case 'alpha_type', i=i+1; sTrain.alpha_type = varargin{i};
|
wolffd@0
|
314 case 'alpha_ini', i=i+1; sTrain.alpha_ini = varargin{i};
|
wolffd@0
|
315 case 'alpha',
|
wolffd@0
|
316 i=i+1;
|
wolffd@0
|
317 sTrain.alpha_ini = varargin{i}(1);
|
wolffd@0
|
318 if length(varargin{i})>1,
|
wolffd@0
|
319 alpha = varargin{i}; tlen_type = 'samples';
|
wolffd@0
|
320 sTrain.alpha_type = 'user defined';
|
wolffd@0
|
321 end
|
wolffd@0
|
322 case {'sTrain','train','som_train'}, i=i+1; sTrain = varargin{i};
|
wolffd@0
|
323 case {'topol','sTopol','som_topol'},
|
wolffd@0
|
324 i=i+1;
|
wolffd@0
|
325 sTopol = varargin{i};
|
wolffd@0
|
326 if prod(sTopol.msize) ~= munits,
|
wolffd@0
|
327 error('Given map grid size does not match the codebook size.');
|
wolffd@0
|
328 end
|
wolffd@0
|
329 % unambiguous values
|
wolffd@0
|
330 case {'inv','linear','power'}, sTrain.alpha_type = varargin{i};
|
wolffd@0
|
331 case {'hexa','rect'}, sTopol.lattice = varargin{i};
|
wolffd@0
|
332 case {'sheet','cyl','toroid'}, sTopol.shape = varargin{i};
|
wolffd@0
|
333 case {'gaussian','cutgauss','ep','bubble'}, sTrain.neigh = varargin{i};
|
wolffd@0
|
334 case {'epochs','samples'}, tlen_type = varargin{i};
|
wolffd@0
|
335 case {'random', 'ordered'}, sample_order_type = varargin{i};
|
wolffd@0
|
336 otherwise argok=0;
|
wolffd@0
|
337 end
|
wolffd@0
|
338 elseif isstruct(varargin{i}) & isfield(varargin{i},'type'),
|
wolffd@0
|
339 switch varargin{i}(1).type,
|
wolffd@0
|
340 case 'som_topol',
|
wolffd@0
|
341 sTopol = varargin{i};
|
wolffd@0
|
342 if prod(sTopol.msize) ~= munits,
|
wolffd@0
|
343 error('Given map grid size does not match the codebook size.');
|
wolffd@0
|
344 end
|
wolffd@0
|
345 case 'som_train', sTrain = varargin{i};
|
wolffd@0
|
346 otherwise argok=0;
|
wolffd@0
|
347 end
|
wolffd@0
|
348 else
|
wolffd@0
|
349 argok = 0;
|
wolffd@0
|
350 end
|
wolffd@0
|
351 if ~argok,
|
wolffd@0
|
352 disp(['(som_seqtrain) Ignoring invalid argument #' num2str(i+2)]);
|
wolffd@0
|
353 end
|
wolffd@0
|
354 i = i+1;
|
wolffd@0
|
355 end
|
wolffd@0
|
356
|
wolffd@0
|
357 % training length
|
wolffd@0
|
358 if ~isempty(radius) | ~isempty(alpha),
|
wolffd@0
|
359 lr = length(radius);
|
wolffd@0
|
360 la = length(alpha);
|
wolffd@0
|
361 if lr>2 | la>1,
|
wolffd@0
|
362 tlen_type = 'samples';
|
wolffd@0
|
363 if lr> 2 & la<=1, sTrain.trainlen = lr;
|
wolffd@0
|
364 elseif lr<=2 & la> 1, sTrain.trainlen = la;
|
wolffd@0
|
365 elseif lr==la, sTrain.trainlen = la;
|
wolffd@0
|
366 else
|
wolffd@0
|
367 error('Mismatch between radius and learning rate vector lengths.')
|
wolffd@0
|
368 end
|
wolffd@0
|
369 end
|
wolffd@0
|
370 end
|
wolffd@0
|
371 if strcmp(tlen_type,'samples'), sTrain.trainlen = sTrain.trainlen/dlen; end
|
wolffd@0
|
372
|
wolffd@0
|
373 % check topology
|
wolffd@0
|
374 if struct_mode,
|
wolffd@0
|
375 if ~strcmp(sTopol.lattice,sMap.topol.lattice) | ...
|
wolffd@0
|
376 ~strcmp(sTopol.shape,sMap.topol.shape) | ...
|
wolffd@0
|
377 any(sTopol.msize ~= sMap.topol.msize),
|
wolffd@0
|
378 warning('Changing the original map topology.');
|
wolffd@0
|
379 end
|
wolffd@0
|
380 end
|
wolffd@0
|
381 sMap.topol = sTopol;
|
wolffd@0
|
382
|
wolffd@0
|
383 % complement the training struct
|
wolffd@0
|
384 sTrain = som_train_struct(sTrain,sMap,'dlen',dlen);
|
wolffd@0
|
385 if isempty(sTrain.mask), sTrain.mask = ones(dim,1); end
|
wolffd@0
|
386
|
wolffd@0
|
387 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
wolffd@0
|
388 %% initialize
|
wolffd@0
|
389
|
wolffd@0
|
390 M = sMap.codebook;
|
wolffd@0
|
391 mask = sTrain.mask;
|
wolffd@0
|
392 trainlen = sTrain.trainlen*dlen;
|
wolffd@0
|
393
|
wolffd@0
|
394 % neighborhood radius
|
wolffd@0
|
395 if length(radius)>2,
|
wolffd@0
|
396 radius_type = 'user defined';
|
wolffd@0
|
397 else
|
wolffd@0
|
398 radius = [sTrain.radius_ini sTrain.radius_fin];
|
wolffd@0
|
399 rini = radius(1);
|
wolffd@0
|
400 rstep = (radius(end)-radius(1))/(trainlen-1);
|
wolffd@0
|
401 radius_type = 'linear';
|
wolffd@0
|
402 end
|
wolffd@0
|
403
|
wolffd@0
|
404 % learning rate
|
wolffd@0
|
405 if length(alpha)>1,
|
wolffd@0
|
406 sTrain.alpha_type ='user defined';
|
wolffd@0
|
407 if length(alpha) ~= trainlen,
|
wolffd@0
|
408 error('Trainlen and length of neighborhood radius vector do not match.')
|
wolffd@0
|
409 end
|
wolffd@0
|
410 if any(isnan(alpha)),
|
wolffd@0
|
411 error('NaN is an illegal learning rate.')
|
wolffd@0
|
412 end
|
wolffd@0
|
413 else
|
wolffd@0
|
414 if isempty(alpha), alpha = sTrain.alpha_ini; end
|
wolffd@0
|
415 if strcmp(sTrain.alpha_type,'inv'),
|
wolffd@0
|
416 % alpha(t) = a / (t+b), where a and b are chosen suitably
|
wolffd@0
|
417 % below, they are chosen so that alpha_fin = alpha_ini/100
|
wolffd@0
|
418 b = (trainlen - 1) / (100 - 1);
|
wolffd@0
|
419 a = b * alpha;
|
wolffd@0
|
420 end
|
wolffd@0
|
421 end
|
wolffd@0
|
422
|
wolffd@0
|
423 % initialize random number generator
|
wolffd@0
|
424 rand('state',sum(100*clock));
|
wolffd@0
|
425
|
wolffd@0
|
426 % distance between map units in the output space
|
wolffd@0
|
427 % Since in the case of gaussian and ep neighborhood functions, the
|
wolffd@0
|
428 % equations utilize squares of the unit distances and in bubble case
|
wolffd@0
|
429 % it doesn't matter which is used, the unitdistances and neighborhood
|
wolffd@0
|
430 % radiuses are squared.
|
wolffd@0
|
431 Ud = som_unit_dists(sTopol).^2;
|
wolffd@0
|
432
|
wolffd@0
|
433 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
wolffd@0
|
434 %% Action
|
wolffd@0
|
435
|
wolffd@0
|
436 update_step = 100;
|
wolffd@0
|
437 mu_x_1 = ones(munits,1);
|
wolffd@0
|
438 samples = ones(update_step,1);
|
wolffd@0
|
439 r = samples;
|
wolffd@0
|
440 alfa = samples;
|
wolffd@0
|
441
|
wolffd@0
|
442 qe = 0;
|
wolffd@0
|
443 start = clock;
|
wolffd@0
|
444 if tracking > 0, % initialize tracking
|
wolffd@0
|
445 track_table = zeros(update_step,1);
|
wolffd@0
|
446 qe = zeros(floor(trainlen/update_step),1);
|
wolffd@0
|
447 end
|
wolffd@0
|
448
|
wolffd@0
|
449 for t = 1:trainlen,
|
wolffd@0
|
450
|
wolffd@0
|
451 % Every update_step, new values for sample indeces, neighborhood
|
wolffd@0
|
452 % radius and learning rate are calculated. This could be done
|
wolffd@0
|
453 % every step, but this way it is more efficient. Or this could
|
wolffd@0
|
454 % be done all at once outside the loop, but it would require much
|
wolffd@0
|
455 % more memory.
|
wolffd@0
|
456 ind = rem(t,update_step); if ind==0, ind = update_step; end
|
wolffd@0
|
457 if ind==1,
|
wolffd@0
|
458 steps = [t:min(trainlen,t+update_step-1)];
|
wolffd@0
|
459 % sample order
|
wolffd@0
|
460 switch sample_order_type,
|
wolffd@0
|
461 case 'ordered', samples = rem(steps,dlen)+1;
|
wolffd@0
|
462 case 'random', samples = ceil(dlen*rand(update_step,1)+eps);
|
wolffd@0
|
463 end
|
wolffd@0
|
464
|
wolffd@0
|
465 % neighborhood radius
|
wolffd@0
|
466 switch radius_type,
|
wolffd@0
|
467 case 'linear', r = rini+(steps-1)*rstep;
|
wolffd@0
|
468 case 'user defined', r = radius(steps);
|
wolffd@0
|
469 end
|
wolffd@0
|
470 r=r.^2; % squared radius (see notes about Ud above)
|
wolffd@0
|
471 r(r==0) = eps; % zero radius might cause div-by-zero error
|
wolffd@0
|
472
|
wolffd@0
|
473 % learning rate
|
wolffd@0
|
474 switch sTrain.alpha_type,
|
wolffd@0
|
475 case 'linear', alfa = (1-steps/trainlen)*alpha;
|
wolffd@0
|
476 case 'inv', alfa = a ./ (b + steps-1);
|
wolffd@0
|
477 case 'power', alfa = alpha * (0.005/alpha).^((steps-1)/trainlen);
|
wolffd@0
|
478 case 'user defined', alfa = alpha(steps);
|
wolffd@0
|
479 end
|
wolffd@0
|
480 end
|
wolffd@0
|
481
|
wolffd@0
|
482 % find BMU
|
wolffd@0
|
483 x = D(samples(ind),:); % pick one sample vector
|
wolffd@0
|
484 known = ~isnan(x); % its known components
|
wolffd@0
|
485 Dx = M(:,known) - x(mu_x_1,known); % each map unit minus the vector
|
wolffd@0
|
486 [qerr bmu] = min((Dx.^2)*mask(known)); % minimum distance(^2) and the BMU
|
wolffd@0
|
487
|
wolffd@0
|
488 % tracking
|
wolffd@0
|
489 if tracking>0,
|
wolffd@0
|
490 track_table(ind) = sqrt(qerr);
|
wolffd@0
|
491 if ind==update_step,
|
wolffd@0
|
492 n = ceil(t/update_step);
|
wolffd@0
|
493 qe(n) = mean(track_table);
|
wolffd@0
|
494 trackplot(M,D,tracking,start,n,qe);
|
wolffd@0
|
495 end
|
wolffd@0
|
496 end
|
wolffd@0
|
497
|
wolffd@0
|
498 % neighborhood & learning rate
|
wolffd@0
|
499 % notice that the elements Ud and radius have been squared!
|
wolffd@0
|
500 % (see notes about Ud above)
|
wolffd@0
|
501 switch sTrain.neigh,
|
wolffd@0
|
502 case 'bubble', h = (Ud(:,bmu)<=r(ind));
|
wolffd@0
|
503 case 'gaussian', h = exp(-Ud(:,bmu)/(2*r(ind)));
|
wolffd@0
|
504 case 'cutgauss', h = exp(-Ud(:,bmu)/(2*r(ind))) .* (Ud(:,bmu)<=r(ind));
|
wolffd@0
|
505 case 'ep', h = (1-Ud(:,bmu)/r(ind)) .* (Ud(:,bmu)<=r(ind));
|
wolffd@0
|
506 end
|
wolffd@0
|
507 h = h*alfa(ind);
|
wolffd@0
|
508
|
wolffd@0
|
509 % update M
|
wolffd@0
|
510 M(:,known) = M(:,known) - h(:,ones(sum(known),1)).*Dx;
|
wolffd@0
|
511
|
wolffd@0
|
512 end; % for t = 1:trainlen
|
wolffd@0
|
513
|
wolffd@0
|
514 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
wolffd@0
|
515 %% Build / clean up the return arguments
|
wolffd@0
|
516
|
wolffd@0
|
517 if tracking, fprintf(1,'\n'); end
|
wolffd@0
|
518
|
wolffd@0
|
519 % update structures
|
wolffd@0
|
520 sTrain = som_set(sTrain,'time',datestr(now,0));
|
wolffd@0
|
521 if struct_mode,
|
wolffd@0
|
522 sMap = som_set(sMap,'codebook',M,'mask',sTrain.mask,'neigh',sTrain.neigh);
|
wolffd@0
|
523 tl = length(sMap.trainhist);
|
wolffd@0
|
524 sMap.trainhist(tl+1) = sTrain;
|
wolffd@0
|
525 else
|
wolffd@0
|
526 sMap = reshape(M,orig_size);
|
wolffd@0
|
527 end
|
wolffd@0
|
528
|
wolffd@0
|
529 return;
|
wolffd@0
|
530
|
wolffd@0
|
531
|
wolffd@0
|
532
|
wolffd@0
|
533 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
wolffd@0
|
534 %% subfunctions
|
wolffd@0
|
535
|
wolffd@0
|
536 %%%%%%%%
|
wolffd@0
|
537 function [] = trackplot(M,D,tracking,start,n,qe)
|
wolffd@0
|
538
|
wolffd@0
|
539 l = length(qe);
|
wolffd@0
|
540 elap_t = etime(clock,start);
|
wolffd@0
|
541 tot_t = elap_t*l/n;
|
wolffd@0
|
542 fprintf(1,'\rTraining: %3.0f/ %3.0f s',elap_t,tot_t)
|
wolffd@0
|
543 switch tracking
|
wolffd@0
|
544 case 1,
|
wolffd@0
|
545 case 2,
|
wolffd@0
|
546 plot(1:n,qe(1:n),(n+1):l,qe((n+1):l))
|
wolffd@0
|
547 title('Quantization errors for latest samples')
|
wolffd@0
|
548 drawnow
|
wolffd@0
|
549 otherwise,
|
wolffd@0
|
550 subplot(2,1,1), plot(1:n,qe(1:n),(n+1):l,qe((n+1):l))
|
wolffd@0
|
551 title('Quantization error for latest samples');
|
wolffd@0
|
552 subplot(2,1,2), plot(M(:,1),M(:,2),'ro',D(:,1),D(:,2),'b.');
|
wolffd@0
|
553 title('First two components of map units (o) and data vectors (+)');
|
wolffd@0
|
554 drawnow
|
wolffd@0
|
555 end
|
wolffd@0
|
556 % end of trackplot
|
wolffd@0
|
557
|