wolffd@0
|
1 function [sM,sTrain] = som_prototrain(sM, D)
|
wolffd@0
|
2
|
wolffd@0
|
3 %SOM_PROTOTRAIN Use sequential algorithm to train the Self-Organizing Map.
|
wolffd@0
|
4 %
|
wolffd@0
|
5 % [sM,sT] = som_prototrain(sM, D)
|
wolffd@0
|
6 %
|
wolffd@0
|
7 % sM = som_prototrain(sM,D);
|
wolffd@0
|
8 %
|
wolffd@0
|
9 % Input and output arguments:
|
wolffd@0
|
10 % sM (struct) map struct, the trained and updated map is returned
|
wolffd@0
|
11 % (matrix) codebook matrix of a self-organizing map
|
wolffd@0
|
12 % size munits x dim or msize(1) x ... x msize(k) x dim
|
wolffd@0
|
13 % The trained map codebook is returned.
|
wolffd@0
|
14 % D (struct) training data; data struct
|
wolffd@0
|
15 % (matrix) training data, size dlen x dim
|
wolffd@0
|
16 %
|
wolffd@0
|
17 % This function is otherwise just like SOM_SEQTRAIN except that
|
wolffd@0
|
18 % the implementation of the sequential training algorithm is very
|
wolffd@0
|
19 % straightforward (and slower). This should make it easy for you
|
wolffd@0
|
20 % to modify the algorithm, if you want to.
|
wolffd@0
|
21 %
|
wolffd@0
|
22 % For help on input and output parameters, try
|
wolffd@0
|
23 % 'type som_prototrain' or check out the help for SOM_SEQTRAIN.
|
wolffd@0
|
24 % See also SOM_SEQTRAIN, SOM_BATCHTRAIN.
|
wolffd@0
|
25
|
wolffd@0
|
26 % Contributed to SOM Toolbox vs2, February 2nd, 2000 by Juha Vesanto
|
wolffd@0
|
27 % http://www.cis.hut.fi/projects/somtoolbox/
|
wolffd@0
|
28
|
wolffd@0
|
29 % Version 2.0beta juuso 080200 130300
|
wolffd@0
|
30
|
wolffd@0
|
31 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
wolffd@0
|
32 %% Check input arguments
|
wolffd@0
|
33
|
wolffd@0
|
34 % map
|
wolffd@0
|
35 struct_mode = isstruct(sM);
|
wolffd@0
|
36 if struct_mode,
|
wolffd@0
|
37 M = sM.codebook;
|
wolffd@0
|
38 sTopol = sM.topol;
|
wolffd@0
|
39 mask = sM.mask;
|
wolffd@0
|
40 msize = sTopol.msize;
|
wolffd@0
|
41 neigh = sM.neigh;
|
wolffd@0
|
42 else
|
wolffd@0
|
43 M = sM; orig_size = size(M);
|
wolffd@0
|
44 if ndims(sM) > 2,
|
wolffd@0
|
45 si = size(sM); dim = si(end); msize = si(1:end-1);
|
wolffd@0
|
46 M = reshape(sM,[prod(msize) dim]);
|
wolffd@0
|
47 else
|
wolffd@0
|
48 msize = [orig_size(1) 1]; dim = orig_size(2);
|
wolffd@0
|
49 end
|
wolffd@0
|
50 sM = som_map_struct(dim,'msize',msize); sTopol = sM.topol;
|
wolffd@0
|
51 mask = ones(dim,1);
|
wolffd@0
|
52 neigh = 'gaussian';
|
wolffd@0
|
53 end
|
wolffd@0
|
54 [munits dim] = size(M);
|
wolffd@0
|
55
|
wolffd@0
|
56 % data
|
wolffd@0
|
57 if isstruct(D), data_name = D.name; D = D.data;
|
wolffd@0
|
58 else data_name = inputname(2);
|
wolffd@0
|
59 end
|
wolffd@0
|
60 D = D(find(sum(isnan(D),2) < dim),:); % remove empty vectors from the data
|
wolffd@0
|
61 [dlen ddim] = size(D); % check input dimension
|
wolffd@0
|
62 if dim ~= ddim, error('Map and data input space dimensions disagree.'); end
|
wolffd@0
|
63
|
wolffd@0
|
64 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
wolffd@0
|
65 %% initialize (these are default values, change as you will)
|
wolffd@0
|
66
|
wolffd@0
|
67 % training length
|
wolffd@0
|
68 trainlen = 20*dlen; % 20 epochs by default
|
wolffd@0
|
69
|
wolffd@0
|
70 % neighborhood radius
|
wolffd@0
|
71 radius_type = 'linear';
|
wolffd@0
|
72 rini = max(msize)/2;
|
wolffd@0
|
73 rfin = 1;
|
wolffd@0
|
74
|
wolffd@0
|
75 % learning rate
|
wolffd@0
|
76 alpha_type = 'inv';
|
wolffd@0
|
77 alpha_ini = 0.2;
|
wolffd@0
|
78
|
wolffd@0
|
79 % initialize random number generator
|
wolffd@0
|
80 rand('state',sum(100*clock));
|
wolffd@0
|
81
|
wolffd@0
|
82 % tracking
|
wolffd@0
|
83 start = clock; trackstep = 100;
|
wolffd@0
|
84
|
wolffd@0
|
85 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
wolffd@0
|
86 %% Action
|
wolffd@0
|
87
|
wolffd@0
|
88 Ud = som_unit_dists(sTopol); % distance between map units on the grid
|
wolffd@0
|
89 mu_x_1 = ones(munits,1); % this is used pretty often
|
wolffd@0
|
90
|
wolffd@0
|
91 for t = 1:trainlen,
|
wolffd@0
|
92
|
wolffd@0
|
93 %% find BMU
|
wolffd@0
|
94 ind = ceil(dlen*rand(1)+eps); % select one vector
|
wolffd@0
|
95 x = D(ind,:); % pick it up
|
wolffd@0
|
96 known = ~isnan(x); % its known components
|
wolffd@0
|
97 Dx = M(:,known) - x(mu_x_1,known); % each map unit minus the vector
|
wolffd@0
|
98 dist2 = (Dx.^2)*mask(known); % squared distances
|
wolffd@0
|
99 [qerr bmu] = min(dist2); % find BMU
|
wolffd@0
|
100
|
wolffd@0
|
101 %% neighborhood
|
wolffd@0
|
102 switch radius_type, % radius
|
wolffd@0
|
103 case 'linear', r = rini+(rfin-rini)*(t-1)/(trainlen-1);
|
wolffd@0
|
104 end
|
wolffd@0
|
105 if ~r, r=eps; end % zero neighborhood radius may cause div-by-zero error
|
wolffd@0
|
106 switch neigh, % neighborhood function
|
wolffd@0
|
107 case 'bubble', h = (Ud(:,bmu) <= r);
|
wolffd@0
|
108 case 'gaussian', h = exp(-(Ud(:,bmu).^2)/(2*r*r));
|
wolffd@0
|
109 case 'cutgauss', h = exp(-(Ud(:,bmu).^2)/(2*r*r)) .* (Ud(:,bmu) <= r);
|
wolffd@0
|
110 case 'ep', h = (1 - (Ud(:,bmu).^2)/(r*r)) .* (Ud(:,bmu) <= r);
|
wolffd@0
|
111 end
|
wolffd@0
|
112
|
wolffd@0
|
113 %% learning rate
|
wolffd@0
|
114 switch alpha_type,
|
wolffd@0
|
115 case 'linear', a = (1-t/trainlen)*alpha_ini;
|
wolffd@0
|
116 case 'inv', a = alpha_ini / (1 + 99*(t-1)/(trainlen-1));
|
wolffd@0
|
117 case 'power', a = alpha_ini * (0.005/alpha_ini)^((t-1)/trainlen);
|
wolffd@0
|
118 end
|
wolffd@0
|
119
|
wolffd@0
|
120 %% update
|
wolffd@0
|
121 M(:,known) = M(:,known) - a*h(:,ones(sum(known),1)).*Dx;
|
wolffd@0
|
122
|
wolffd@0
|
123 %% tracking
|
wolffd@0
|
124 if t==1 | ~rem(t,trackstep),
|
wolffd@0
|
125 elap_t = etime(clock,start); tot_t = elap_t*trainlen/t;
|
wolffd@0
|
126 fprintf(1,'\rTraining: %3.0f/ %3.0f s',elap_t,tot_t)
|
wolffd@0
|
127 end
|
wolffd@0
|
128
|
wolffd@0
|
129 end; % for t = 1:trainlen
|
wolffd@0
|
130 fprintf(1,'\n');
|
wolffd@0
|
131
|
wolffd@0
|
132 % outputs
|
wolffd@0
|
133 sTrain = som_set('som_train','algorithm','proto',...
|
wolffd@0
|
134 'data_name',data_name,...
|
wolffd@0
|
135 'neigh',neigh,...
|
wolffd@0
|
136 'mask',mask,...
|
wolffd@0
|
137 'radius_ini',rini,...
|
wolffd@0
|
138 'radius_fin',rfin,...
|
wolffd@0
|
139 'alpha_ini',alpha_ini,...
|
wolffd@0
|
140 'alpha_type',alpha_type,...
|
wolffd@0
|
141 'trainlen',trainlen,...
|
wolffd@0
|
142 'time',datestr(now,0));
|
wolffd@0
|
143
|
wolffd@0
|
144 if struct_mode,
|
wolffd@0
|
145 sM = som_set(sM,'codebook',M,'mask',mask,'neigh',neigh);
|
wolffd@0
|
146 sM.trainhist(end+1) = sTrain;
|
wolffd@0
|
147 else
|
wolffd@0
|
148 sM = reshape(M,orig_size);
|
wolffd@0
|
149 end
|
wolffd@0
|
150
|
wolffd@0
|
151 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
wolffd@0
|
152
|
wolffd@0
|
153
|
wolffd@0
|
154
|
wolffd@0
|
155
|