Daniel@0: function codebook=lvq1(codebook, data, rlen, alpha); Daniel@0: Daniel@0: %LVQ1 Trains a codebook with the LVQ1 -algorithm. Daniel@0: % Daniel@0: % sM = lvq1(sM, D, rlen, alpha) Daniel@0: % Daniel@0: % sM = lvq1(sM,sD,30*length(sM.codebook),0.08); Daniel@0: % Daniel@0: % Input and output arguments: Daniel@0: % sM (struct) map struct, the class information must be Daniel@0: % present on the first column of .labels field Daniel@0: % D (struct) data struct, the class information must Daniel@0: % be present on the first column of .labels field Daniel@0: % rlen (scalar) running length Daniel@0: % alpha (scalar) learning parameter Daniel@0: % Daniel@0: % sM (struct) map struct, the trained codebook Daniel@0: % Daniel@0: % NOTE: does not take mask into account. Daniel@0: % Daniel@0: % For more help, try 'type lvq1', or check out online documentation. Daniel@0: % See also LVQ3, SOM_SUPERVISED, SOM_SEQTRAIN. Daniel@0: Daniel@0: %%%%%%%%%%%%% DETAILED DESCRIPTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Daniel@0: % Daniel@0: % lvq1 Daniel@0: % Daniel@0: % PURPOSE Daniel@0: % Daniel@0: % Trains codebook with the LVQ1 -algorithm (described below). Daniel@0: % Daniel@0: % SYNTAX Daniel@0: % Daniel@0: % sM = lvq1(sM, D, rlen, alpha) Daniel@0: % Daniel@0: % DESCRIPTION Daniel@0: % Daniel@0: % Trains codebook with the LVQ1 -algorithm. Codebook contains a number Daniel@0: % of vectors (mi, i=1,2,...,n) and so does data (vectors xj, Daniel@0: % j=1,2,...,k). Both vector sets are classified: vectors may have a Daniel@0: % class (classes are set to the first column of data or map -structs' Daniel@0: % .labels -field). For each xj there is defined the nearest codebook Daniel@0: % -vector index c by searching the minimum of the euclidean distances Daniel@0: % between the current xj and codebook -vectors: Daniel@0: % Daniel@0: % c = min{ ||xj - mi|| }, i=[1,..,n], for fixed xj Daniel@0: % i Daniel@0: % If xj and mc belong to the same class, mc is updated as follows: Daniel@0: % mc(t+1) = mc(t) + alpha * (xj(t) - mc(t)) Daniel@0: % If xj and mc belong to different classes, mc is updated as follows: Daniel@0: % mc(t+1) = mc(t) - alpha * (xj(t) - mc(t)) Daniel@0: % Otherwise updating is not performed. Daniel@0: % Daniel@0: % Argument 'rlen' tells how many times training sequence is performed. Daniel@0: % LVQ1 -algorithm may be stopped after a number of steps, that is Daniel@0: % 30-50 times the number of codebook vectors. Daniel@0: % Daniel@0: % Argument 'alpha' is the learning rate, recommended to be smaller Daniel@0: % than 0.1. Daniel@0: % Daniel@0: % NOTE: does not take mask into account. Daniel@0: % Daniel@0: % REFERENCES Daniel@0: % Daniel@0: % Kohonen, T., "Self-Organizing Map", 2nd ed., Springer-Verlag, Daniel@0: % Berlin, 1995, pp. 176-179. Daniel@0: % Daniel@0: % See also LVQ_PAK from http://www.cis.hut.fi/research/som_lvq_pak.shtml Daniel@0: % Daniel@0: % REQUIRED INPUT ARGUMENTS Daniel@0: % Daniel@0: % sM The data to be trained. Daniel@0: % (struct) A map struct. Daniel@0: % Daniel@0: % D The data to use in training. Daniel@0: % (struct) A data struct. Daniel@0: % Daniel@0: % rlen (integer) Running length of LVQ1 -algorithm. Daniel@0: % Daniel@0: % alpha (float) Learning rate used in training. Daniel@0: % Daniel@0: % OUTPUT ARGUMENTS Daniel@0: % Daniel@0: % codebook Trained data. Daniel@0: % (struct) A map struct. Daniel@0: % Daniel@0: % EXAMPLE Daniel@0: % Daniel@0: % lab = unique(sD.labels(:,1)); % different classes Daniel@0: % mu = length(lab)*5; % 5 prototypes for each Daniel@0: % sM = som_randinit(sD,'msize',[mu 1]); % initial prototypes Daniel@0: % sM.labels = [lab;lab;lab;lab;lab]; % their classes Daniel@0: % sM = lvq1(sM,sD,50*mu,0.05); % use LVQ1 to adjust Daniel@0: % % the prototypes Daniel@0: % sM = lvq3(sM,sD,50*mu,0.05,0.2,0.3); % then use LVQ3 Daniel@0: % Daniel@0: % SEE ALSO Daniel@0: % Daniel@0: % lvq3 Use LVQ3 algorithm for training. Daniel@0: % som_supervised Train SOM using supervised training. Daniel@0: % som_seqtrain Train SOM with sequential algorithm. Daniel@0: Daniel@0: % Contributed to SOM Toolbox vs2, February 2nd, 2000 by Juha Parhankangas Daniel@0: % Copyright (c) Juha Parhankangas Daniel@0: % http://www.cis.hut.fi/projects/somtoolbox/ Daniel@0: Daniel@0: % Juha Parhankangas 310100 juuso 020200 Daniel@0: Daniel@0: cod = codebook.codebook; Daniel@0: c_class = class2num(codebook.labels(:,1)); Daniel@0: Daniel@0: dat = data.data; Daniel@0: d_class = class2num(data.labels(:,1)); Daniel@0: Daniel@0: x=size(dat,1); Daniel@0: y=size(cod,2); Daniel@0: Daniel@0: ONES=ones(size(cod,1),1); Daniel@0: Daniel@0: for t=1:rlen Daniel@0: Daniel@0: fprintf(1,'\rTraining round: %d',t); Daniel@0: tmp=NaN*ones(x,y); Daniel@0: Daniel@0: for j=1:x Daniel@0: no_NaN=find(~isnan(dat(j,:))); Daniel@0: di = sqrt(sum([cod(:,no_NaN) - ONES*dat(j,no_NaN)].^2,2)); Daniel@0: Daniel@0: [foo,ind] = min(di); Daniel@0: Daniel@0: if d_class(j) & d_class(j) == c_class(ind) % 0 is for unclassified vectors Daniel@0: tmp(ind,:) = cod(ind,:) + alpha * (dat(j,:) - cod(ind,:)); Daniel@0: elseif d_class(j) Daniel@0: tmp(ind,:) = cod(ind,:) - alpha*(dat(j,:) - cod(ind,:)); Daniel@0: end Daniel@0: end Daniel@0: Daniel@0: inds = find(~isnan(sum(tmp,2))); Daniel@0: cod(inds,:) = tmp(inds,:); Daniel@0: end Daniel@0: Daniel@0: codebook.codebook = cod; Daniel@0: Daniel@0: sTrain = som_set('som_train','algorithm','lvq1',... Daniel@0: 'data_name',data.name,... Daniel@0: 'neigh','',... Daniel@0: 'mask',ones(y,1),... Daniel@0: 'radius_ini',NaN,... Daniel@0: 'radius_fin',NaN,... Daniel@0: 'alpha_ini',alpha,... Daniel@0: 'alpha_type','constant',... Daniel@0: 'trainlen',rlen,... Daniel@0: 'time',datestr(now,0)); Daniel@0: codebook.trainhist(end+1) = sTrain; Daniel@0: Daniel@0: return; Daniel@0: Daniel@0: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Daniel@0: Daniel@0: function nos = class2num(class) Daniel@0: Daniel@0: names = {}; Daniel@0: nos = zeros(length(class),1); Daniel@0: Daniel@0: for i=1:length(class) Daniel@0: if ~isempty(class{i}) & ~any(strcmp(class{i},names)) Daniel@0: names=cat(1,names,class(i)); Daniel@0: end Daniel@0: end Daniel@0: Daniel@0: tmp_nos = (1:length(names))'; Daniel@0: Daniel@0: for i=1:length(class) Daniel@0: if ~isempty(class{i}) Daniel@0: nos(i,1) = find(strcmp(class{i},names)); Daniel@0: end Daniel@0: end Daniel@0: Daniel@0: Daniel@0: