| 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 |