wolffd@0
|
1 function codebook=lvq1(codebook, data, rlen, alpha);
|
wolffd@0
|
2
|
wolffd@0
|
3 %LVQ1 Trains a codebook with the LVQ1 -algorithm.
|
wolffd@0
|
4 %
|
wolffd@0
|
5 % sM = lvq1(sM, D, rlen, alpha)
|
wolffd@0
|
6 %
|
wolffd@0
|
7 % sM = lvq1(sM,sD,30*length(sM.codebook),0.08);
|
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
|
wolffd@0
|
16 %
|
wolffd@0
|
17 % sM (struct) map struct, the trained codebook
|
wolffd@0
|
18 %
|
wolffd@0
|
19 % NOTE: does not take mask into account.
|
wolffd@0
|
20 %
|
wolffd@0
|
21 % For more help, try 'type lvq1', or check out online documentation.
|
wolffd@0
|
22 % See also LVQ3, SOM_SUPERVISED, SOM_SEQTRAIN.
|
wolffd@0
|
23
|
wolffd@0
|
24 %%%%%%%%%%%%% DETAILED DESCRIPTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
wolffd@0
|
25 %
|
wolffd@0
|
26 % lvq1
|
wolffd@0
|
27 %
|
wolffd@0
|
28 % PURPOSE
|
wolffd@0
|
29 %
|
wolffd@0
|
30 % Trains codebook with the LVQ1 -algorithm (described below).
|
wolffd@0
|
31 %
|
wolffd@0
|
32 % SYNTAX
|
wolffd@0
|
33 %
|
wolffd@0
|
34 % sM = lvq1(sM, D, rlen, alpha)
|
wolffd@0
|
35 %
|
wolffd@0
|
36 % DESCRIPTION
|
wolffd@0
|
37 %
|
wolffd@0
|
38 % Trains codebook with the LVQ1 -algorithm. Codebook contains a number
|
wolffd@0
|
39 % of vectors (mi, i=1,2,...,n) and so does data (vectors xj,
|
wolffd@0
|
40 % j=1,2,...,k). Both vector sets are classified: vectors may have a
|
wolffd@0
|
41 % class (classes are set to the first column of data or map -structs'
|
wolffd@0
|
42 % .labels -field). For each xj there is defined the nearest codebook
|
wolffd@0
|
43 % -vector index c by searching the minimum of the euclidean distances
|
wolffd@0
|
44 % between the current xj and codebook -vectors:
|
wolffd@0
|
45 %
|
wolffd@0
|
46 % c = min{ ||xj - mi|| }, i=[1,..,n], for fixed xj
|
wolffd@0
|
47 % i
|
wolffd@0
|
48 % If xj and mc belong to the same class, mc is updated as follows:
|
wolffd@0
|
49 % mc(t+1) = mc(t) + alpha * (xj(t) - mc(t))
|
wolffd@0
|
50 % If xj and mc belong to different classes, mc is updated as follows:
|
wolffd@0
|
51 % mc(t+1) = mc(t) - alpha * (xj(t) - mc(t))
|
wolffd@0
|
52 % Otherwise updating is not performed.
|
wolffd@0
|
53 %
|
wolffd@0
|
54 % Argument 'rlen' tells how many times training sequence is performed.
|
wolffd@0
|
55 % LVQ1 -algorithm may be stopped after a number of steps, that is
|
wolffd@0
|
56 % 30-50 times the number of codebook vectors.
|
wolffd@0
|
57 %
|
wolffd@0
|
58 % Argument 'alpha' is the learning rate, recommended to be smaller
|
wolffd@0
|
59 % than 0.1.
|
wolffd@0
|
60 %
|
wolffd@0
|
61 % NOTE: does not take mask into account.
|
wolffd@0
|
62 %
|
wolffd@0
|
63 % REFERENCES
|
wolffd@0
|
64 %
|
wolffd@0
|
65 % Kohonen, T., "Self-Organizing Map", 2nd ed., Springer-Verlag,
|
wolffd@0
|
66 % Berlin, 1995, pp. 176-179.
|
wolffd@0
|
67 %
|
wolffd@0
|
68 % See also LVQ_PAK from http://www.cis.hut.fi/research/som_lvq_pak.shtml
|
wolffd@0
|
69 %
|
wolffd@0
|
70 % REQUIRED INPUT ARGUMENTS
|
wolffd@0
|
71 %
|
wolffd@0
|
72 % sM The data to be trained.
|
wolffd@0
|
73 % (struct) A map struct.
|
wolffd@0
|
74 %
|
wolffd@0
|
75 % D The data to use in training.
|
wolffd@0
|
76 % (struct) A data struct.
|
wolffd@0
|
77 %
|
wolffd@0
|
78 % rlen (integer) Running length of LVQ1 -algorithm.
|
wolffd@0
|
79 %
|
wolffd@0
|
80 % alpha (float) Learning rate used in training.
|
wolffd@0
|
81 %
|
wolffd@0
|
82 % OUTPUT ARGUMENTS
|
wolffd@0
|
83 %
|
wolffd@0
|
84 % codebook Trained data.
|
wolffd@0
|
85 % (struct) A map struct.
|
wolffd@0
|
86 %
|
wolffd@0
|
87 % EXAMPLE
|
wolffd@0
|
88 %
|
wolffd@0
|
89 % lab = unique(sD.labels(:,1)); % different classes
|
wolffd@0
|
90 % mu = length(lab)*5; % 5 prototypes for each
|
wolffd@0
|
91 % sM = som_randinit(sD,'msize',[mu 1]); % initial prototypes
|
wolffd@0
|
92 % sM.labels = [lab;lab;lab;lab;lab]; % their classes
|
wolffd@0
|
93 % sM = lvq1(sM,sD,50*mu,0.05); % use LVQ1 to adjust
|
wolffd@0
|
94 % % the prototypes
|
wolffd@0
|
95 % sM = lvq3(sM,sD,50*mu,0.05,0.2,0.3); % then use LVQ3
|
wolffd@0
|
96 %
|
wolffd@0
|
97 % SEE ALSO
|
wolffd@0
|
98 %
|
wolffd@0
|
99 % lvq3 Use LVQ3 algorithm for training.
|
wolffd@0
|
100 % som_supervised Train SOM using supervised training.
|
wolffd@0
|
101 % som_seqtrain Train SOM with sequential algorithm.
|
wolffd@0
|
102
|
wolffd@0
|
103 % Contributed to SOM Toolbox vs2, February 2nd, 2000 by Juha Parhankangas
|
wolffd@0
|
104 % Copyright (c) Juha Parhankangas
|
wolffd@0
|
105 % http://www.cis.hut.fi/projects/somtoolbox/
|
wolffd@0
|
106
|
wolffd@0
|
107 % Juha Parhankangas 310100 juuso 020200
|
wolffd@0
|
108
|
wolffd@0
|
109 cod = codebook.codebook;
|
wolffd@0
|
110 c_class = class2num(codebook.labels(:,1));
|
wolffd@0
|
111
|
wolffd@0
|
112 dat = data.data;
|
wolffd@0
|
113 d_class = class2num(data.labels(:,1));
|
wolffd@0
|
114
|
wolffd@0
|
115 x=size(dat,1);
|
wolffd@0
|
116 y=size(cod,2);
|
wolffd@0
|
117
|
wolffd@0
|
118 ONES=ones(size(cod,1),1);
|
wolffd@0
|
119
|
wolffd@0
|
120 for t=1:rlen
|
wolffd@0
|
121
|
wolffd@0
|
122 fprintf(1,'\rTraining round: %d',t);
|
wolffd@0
|
123 tmp=NaN*ones(x,y);
|
wolffd@0
|
124
|
wolffd@0
|
125 for j=1:x
|
wolffd@0
|
126 no_NaN=find(~isnan(dat(j,:)));
|
wolffd@0
|
127 di = sqrt(sum([cod(:,no_NaN) - ONES*dat(j,no_NaN)].^2,2));
|
wolffd@0
|
128
|
wolffd@0
|
129 [foo,ind] = min(di);
|
wolffd@0
|
130
|
wolffd@0
|
131 if d_class(j) & d_class(j) == c_class(ind) % 0 is for unclassified vectors
|
wolffd@0
|
132 tmp(ind,:) = cod(ind,:) + alpha * (dat(j,:) - cod(ind,:));
|
wolffd@0
|
133 elseif d_class(j)
|
wolffd@0
|
134 tmp(ind,:) = cod(ind,:) - alpha*(dat(j,:) - cod(ind,:));
|
wolffd@0
|
135 end
|
wolffd@0
|
136 end
|
wolffd@0
|
137
|
wolffd@0
|
138 inds = find(~isnan(sum(tmp,2)));
|
wolffd@0
|
139 cod(inds,:) = tmp(inds,:);
|
wolffd@0
|
140 end
|
wolffd@0
|
141
|
wolffd@0
|
142 codebook.codebook = cod;
|
wolffd@0
|
143
|
wolffd@0
|
144 sTrain = som_set('som_train','algorithm','lvq1',...
|
wolffd@0
|
145 'data_name',data.name,...
|
wolffd@0
|
146 'neigh','',...
|
wolffd@0
|
147 'mask',ones(y,1),...
|
wolffd@0
|
148 'radius_ini',NaN,...
|
wolffd@0
|
149 'radius_fin',NaN,...
|
wolffd@0
|
150 'alpha_ini',alpha,...
|
wolffd@0
|
151 'alpha_type','constant',...
|
wolffd@0
|
152 'trainlen',rlen,...
|
wolffd@0
|
153 'time',datestr(now,0));
|
wolffd@0
|
154 codebook.trainhist(end+1) = sTrain;
|
wolffd@0
|
155
|
wolffd@0
|
156 return;
|
wolffd@0
|
157
|
wolffd@0
|
158 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
wolffd@0
|
159
|
wolffd@0
|
160 function nos = class2num(class)
|
wolffd@0
|
161
|
wolffd@0
|
162 names = {};
|
wolffd@0
|
163 nos = zeros(length(class),1);
|
wolffd@0
|
164
|
wolffd@0
|
165 for i=1:length(class)
|
wolffd@0
|
166 if ~isempty(class{i}) & ~any(strcmp(class{i},names))
|
wolffd@0
|
167 names=cat(1,names,class(i));
|
wolffd@0
|
168 end
|
wolffd@0
|
169 end
|
wolffd@0
|
170
|
wolffd@0
|
171 tmp_nos = (1:length(names))';
|
wolffd@0
|
172
|
wolffd@0
|
173 for i=1:length(class)
|
wolffd@0
|
174 if ~isempty(class{i})
|
wolffd@0
|
175 nos(i,1) = find(strcmp(class{i},names));
|
wolffd@0
|
176 end
|
wolffd@0
|
177 end
|
wolffd@0
|
178
|
wolffd@0
|
179
|
wolffd@0
|
180
|