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