wolffd@0
|
1 function codebook = lvq3(codebook,data,rlen,alpha,win,epsilon)
|
wolffd@0
|
2
|
wolffd@0
|
3 %LVQ3 trains codebook with LVQ3 -algorithm
|
wolffd@0
|
4 %
|
wolffd@0
|
5 % sM = lvq3(sM,D,rlen,alpha,win,epsilon)
|
wolffd@0
|
6 %
|
wolffd@0
|
7 % sM = lvq3(sM,sD,50*length(sM.codebook),0.05,0.2,0.3);
|
wolffd@0
|
8 %
|
wolffd@0
|
9 % Input and output arguments:
|
wolffd@0
|
10 % sM (struct) map struct, the class information must be
|
wolffd@0
|
11 % present on the first column of .labels field
|
wolffd@0
|
12 % D (struct) data struct, the class information must
|
wolffd@0
|
13 % be present on the first column of .labels field
|
wolffd@0
|
14 % rlen (scalar) running length
|
wolffd@0
|
15 % alpha (scalar) learning parameter, e.g. 0.05
|
wolffd@0
|
16 % win (scalar) window width parameter, e.g. 0.25
|
wolffd@0
|
17 % epsilon (scalar) relative learning parameter, e.g. 0.3
|
wolffd@0
|
18 %
|
wolffd@0
|
19 % sM (struct) map struct, the trained codebook
|
wolffd@0
|
20 %
|
wolffd@0
|
21 % NOTE: does not take mask into account.
|
wolffd@0
|
22 %
|
wolffd@0
|
23 % For more help, try 'type lvq3', or check out online documentation.
|
wolffd@0
|
24 % See also LVQ1, SOM_SUPERVISED, SOM_SEQTRAIN.
|
wolffd@0
|
25
|
wolffd@0
|
26 %%%%%%%%%%%%% DETAILED DESCRIPTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
wolffd@0
|
27 %
|
wolffd@0
|
28 % lvq3
|
wolffd@0
|
29 %
|
wolffd@0
|
30 % PURPOSE
|
wolffd@0
|
31 %
|
wolffd@0
|
32 % Trains codebook with the LVQ3 -algorithm (described below).
|
wolffd@0
|
33 %
|
wolffd@0
|
34 % SYNTAX
|
wolffd@0
|
35 %
|
wolffd@0
|
36 % sM = lvq3(sM, data, rlen, alpha, win, epsilon)
|
wolffd@0
|
37 %
|
wolffd@0
|
38 % DESCRIPTION
|
wolffd@0
|
39 %
|
wolffd@0
|
40 % Trains codebook with the LVQ3 -algorithm. Codebook contains a number
|
wolffd@0
|
41 % of vectors (mi, i=1,2,...,n) and so does data (vectors xj, j=1,2,...k).
|
wolffd@0
|
42 % Both vector sets are classified: vectors may have a class (classes are
|
wolffd@0
|
43 % set to data- or map -structure's 'labels' -field. For each xj the two
|
wolffd@0
|
44 % closest codebookvectors mc1 and mc2 are searched (euclidean distances
|
wolffd@0
|
45 % d1 and d2). xj must fall into the zone of window. That happens if:
|
wolffd@0
|
46 %
|
wolffd@0
|
47 % min(d1/d2, d2/d1) > s, where s = (1-win) / (1+win).
|
wolffd@0
|
48 %
|
wolffd@0
|
49 % If xj belongs to the same class of one of the mc1 and mc1, codebook
|
wolffd@0
|
50 % is updated as follows (let mc1 belong to the same class as xj):
|
wolffd@0
|
51 % mc1(t+1) = mc1(t) + alpha * (xj(t) - mc1(t))
|
wolffd@0
|
52 % mc2(t+1) = mc2(t) - alpha * (xj(t) - mc2(t))
|
wolffd@0
|
53 % If both mc1 and mc2 belong to the same class as xj, codebook is
|
wolffd@0
|
54 % updated as follows:
|
wolffd@0
|
55 % mc1(t+1) = mc1(t) + epsilon * alpha * (xj(t) - mc1(t))
|
wolffd@0
|
56 % mc2(t+1) = mc2(t) + epsilon * alpha * (xj(t) - mc2(t))
|
wolffd@0
|
57 % Otherwise updating is not performed.
|
wolffd@0
|
58 %
|
wolffd@0
|
59 % Argument 'rlen' tells how many times training -sequence is performed.
|
wolffd@0
|
60 %
|
wolffd@0
|
61 % Argument 'alpha' is recommended to be smaller than 0.1 and argument
|
wolffd@0
|
62 % 'epsilon' should be between 0.1 and 0.5.
|
wolffd@0
|
63 %
|
wolffd@0
|
64 % NOTE: does not take mask into account.
|
wolffd@0
|
65 %
|
wolffd@0
|
66 % REFERENCES
|
wolffd@0
|
67 %
|
wolffd@0
|
68 % Kohonen, T., "Self-Organizing Map", 2nd ed., Springer-Verlag,
|
wolffd@0
|
69 % Berlin, 1995, pp. 181-182.
|
wolffd@0
|
70 %
|
wolffd@0
|
71 % See also LVQ_PAK from http://www.cis.hut.fi/research/som_lvq_pak.shtml
|
wolffd@0
|
72 %
|
wolffd@0
|
73 % REQUIRED INPUT ARGUMENTS
|
wolffd@0
|
74 %
|
wolffd@0
|
75 % sM The data to be trained.
|
wolffd@0
|
76 % (struct) A map struct.
|
wolffd@0
|
77 %
|
wolffd@0
|
78 % data The data to use in training.
|
wolffd@0
|
79 % (struct) A data struct.
|
wolffd@0
|
80 %
|
wolffd@0
|
81 % rlen (integer) Running length of LVQ3 -algorithm.
|
wolffd@0
|
82 %
|
wolffd@0
|
83 % alpha (float) Learning rate used in training, e.g. 0.05
|
wolffd@0
|
84 %
|
wolffd@0
|
85 % win (float) Window length, e.g. 0.25
|
wolffd@0
|
86 %
|
wolffd@0
|
87 % epsilon (float) Relative learning parameter, e.g. 0.3
|
wolffd@0
|
88 %
|
wolffd@0
|
89 % OUTPUT ARGUMENTS
|
wolffd@0
|
90 %
|
wolffd@0
|
91 % sM Trained data.
|
wolffd@0
|
92 % (struct) A map struct.
|
wolffd@0
|
93 %
|
wolffd@0
|
94 % EXAMPLE
|
wolffd@0
|
95 %
|
wolffd@0
|
96 % lab = unique(sD.labels(:,1)); % different classes
|
wolffd@0
|
97 % mu = length(lab)*5; % 5 prototypes for each
|
wolffd@0
|
98 % sM = som_randinit(sD,'msize',[mu 1]); % initial prototypes
|
wolffd@0
|
99 % sM.labels = [lab;lab;lab;lab;lab]; % their classes
|
wolffd@0
|
100 % sM = lvq1(sM,sD,50*mu,0.05); % use LVQ1 to adjust
|
wolffd@0
|
101 % % the prototypes
|
wolffd@0
|
102 % sM = lvq3(sM,sD,50*mu,0.05,0.2,0.3); % then use LVQ3
|
wolffd@0
|
103 %
|
wolffd@0
|
104 % SEE ALSO
|
wolffd@0
|
105 %
|
wolffd@0
|
106 % lvq1 Use LVQ1 algorithm for training.
|
wolffd@0
|
107 % som_supervised Train SOM using supervised training.
|
wolffd@0
|
108 % som_seqtrain Train SOM with sequential algorithm.
|
wolffd@0
|
109
|
wolffd@0
|
110 % Contributed to SOM Toolbox vs2, February 2nd, 2000 by Juha Parhankangas
|
wolffd@0
|
111 % Copyright (c) by Juha Parhankangas
|
wolffd@0
|
112 % http://www.cis.hut.fi/projects/somtoolbox/
|
wolffd@0
|
113
|
wolffd@0
|
114 % Juha Parhankangas 310100 juuso 020200
|
wolffd@0
|
115
|
wolffd@0
|
116 NOTFOUND = 1;
|
wolffd@0
|
117
|
wolffd@0
|
118 cod = codebook.codebook;
|
wolffd@0
|
119 dat = data.data;
|
wolffd@0
|
120
|
wolffd@0
|
121 c_class = codebook.labels(:,1);
|
wolffd@0
|
122 d_class = data.labels(:,1);
|
wolffd@0
|
123
|
wolffd@0
|
124 s = (1-win)/(1+win);
|
wolffd@0
|
125
|
wolffd@0
|
126 x = size(dat,1);
|
wolffd@0
|
127 y = size(cod,2);
|
wolffd@0
|
128
|
wolffd@0
|
129 c_class=class2num(c_class);
|
wolffd@0
|
130 d_class=class2num(d_class);
|
wolffd@0
|
131
|
wolffd@0
|
132 ONES=ones(size(cod,1),1);
|
wolffd@0
|
133
|
wolffd@0
|
134 for t=1:rlen
|
wolffd@0
|
135 fprintf('\rTraining round: %d/%d',t,rlen);
|
wolffd@0
|
136 tmp = NaN*ones(x,y);
|
wolffd@0
|
137
|
wolffd@0
|
138 for j=1:x
|
wolffd@0
|
139 flag = 0;
|
wolffd@0
|
140 mj = 0;
|
wolffd@0
|
141 mi = 0;
|
wolffd@0
|
142 no_NaN=find(~isnan(dat(j,:)));
|
wolffd@0
|
143 di=sqrt(sum([cod(:,no_NaN) - ONES*dat(j,no_NaN)].^2,2));
|
wolffd@0
|
144 [foo, ind1] = min(di);
|
wolffd@0
|
145 di(ind1)=Inf;
|
wolffd@0
|
146 [foo,ind2] = min(di);
|
wolffd@0
|
147
|
wolffd@0
|
148 %ind2=ind2+1;
|
wolffd@0
|
149
|
wolffd@0
|
150 if d_class(j) & d_class(j)==c_class(ind1)
|
wolffd@0
|
151 mj = ind1;
|
wolffd@0
|
152 mi = ind2;
|
wolffd@0
|
153 if d_class(j)==c_class(ind2)
|
wolffd@0
|
154 flag = 1;
|
wolffd@0
|
155 end
|
wolffd@0
|
156 elseif d_class(j) & d_class(j)==c_class(ind2)
|
wolffd@0
|
157 mj = ind2;
|
wolffd@0
|
158 mi = ind1;
|
wolffd@0
|
159 if d_class(j)==c_class(ind1)
|
wolffd@0
|
160 flag = 1;
|
wolffd@0
|
161 end
|
wolffd@0
|
162 end
|
wolffd@0
|
163
|
wolffd@0
|
164 if mj & mi
|
wolffd@0
|
165 if flag
|
wolffd@0
|
166 tmp([mj mi],:) = cod([mj mi],:) + epsilon*alpha*...
|
wolffd@0
|
167 (dat([j j],:) - cod([mj mi],:));
|
wolffd@0
|
168 else
|
wolffd@0
|
169 tmp(mj,:) = cod(mj,:) + alpha * (dat(j,:)-cod(mj,:));
|
wolffd@0
|
170 tmp(mi,:) = cod(mi,:) - alpha * (dat(j,:)-cod(mj,:));
|
wolffd@0
|
171 end
|
wolffd@0
|
172 end
|
wolffd@0
|
173 end
|
wolffd@0
|
174 inds = find(~isnan(sum(tmp,2)));
|
wolffd@0
|
175 cod(inds,:) = tmp(inds,:);
|
wolffd@0
|
176 end
|
wolffd@0
|
177 fprintf(1,'\n');
|
wolffd@0
|
178
|
wolffd@0
|
179 sTrain = som_set('som_train','algorithm','lvq3',...
|
wolffd@0
|
180 'data_name',data.name,...
|
wolffd@0
|
181 'neigh','',...
|
wolffd@0
|
182 'mask',ones(y,1),...
|
wolffd@0
|
183 'radius_ini',NaN,...
|
wolffd@0
|
184 'radius_fin',NaN,...
|
wolffd@0
|
185 'alpha_ini',alpha,...
|
wolffd@0
|
186 'alpha_type','constant',...
|
wolffd@0
|
187 'trainlen',rlen,...
|
wolffd@0
|
188 'time',datestr(now,0));
|
wolffd@0
|
189 codebook.trainhist(end+1) = sTrain;
|
wolffd@0
|
190
|
wolffd@0
|
191 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
wolffd@0
|
192
|
wolffd@0
|
193 function nos = class2num(class)
|
wolffd@0
|
194
|
wolffd@0
|
195 names = {};
|
wolffd@0
|
196 nos = zeros(length(class),1);
|
wolffd@0
|
197
|
wolffd@0
|
198 for i=1:length(class)
|
wolffd@0
|
199 if ~isempty(class{i}) & ~any(strcmp(class{i},names))
|
wolffd@0
|
200 names=cat(1,names,class(i));
|
wolffd@0
|
201 end
|
wolffd@0
|
202 end
|
wolffd@0
|
203
|
wolffd@0
|
204 tmp_nos = (1:length(names))';
|
wolffd@0
|
205
|
wolffd@0
|
206 for i=1:length(class)
|
wolffd@0
|
207 if ~isempty(class{i})
|
wolffd@0
|
208 nos(i,1) = find(strcmp(class{i},names));
|
wolffd@0
|
209 end
|
wolffd@0
|
210 end
|
wolffd@0
|
211
|
wolffd@0
|
212
|
wolffd@0
|
213
|
wolffd@0
|
214
|
wolffd@0
|
215
|