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