MATLAB gyorstalpaló Neural Network toolbox és SVM-KM toolbox alkalmazása függvényapproximációra, osztályozásra és idősor-előrejelzésre 1 Függvényapproximáció A függvényapproximációt egy egyszerű egydimenziós sinc függvény approximációján keresztül mutatjuk be különböző módszerekkel. Generáljunk először is mintákat a függvényből. Ezzel fogunk majd később tanítani. x = -20:0.1:20; %legyenek az x vektor elemei sorban -20 és 20 között 0.1 -es lépésközzel d = sin(x)./x; %a d vektor elemei legyenek az x vektor elemeinek szinusza, %elemenként elosztva (./) az x vektor elemeivel plot(x,d); %grafikonon ábrázoljuk x vektor függvényében d vektort 1.1 MLP alkalmazása Tanítsuk meg ezt a generált mintakészletet egy MLP-nek a lehető legegyszerűbb módon: net = newff(x,d,15); %MLP létrehozása 1 rejtett réteggel, benne 15 neuronnal. %Minden egyéb paraméter alapértelmezett. net = train(net,x,d); %futtassuk le a tényleges tanítási algoritmust Látható, hogy a Matlab több dolgot is megcsinált. Egyrészt normálta a mintahalmazt, majd felbontotta tanító, teszt, és validációs halmazokra. Az MLP-t pedig az alapértelmezett, Levenberg Marquardt eljárással tanította. Ellenőrizzük a megtanított MLP-t. Először nézzük meg, hogy mi a háló válasza az x=0 helyen, majd ábrázoljuk a tanítópontokat, illetve a háló ezekre adott válaszait egy grafikonon: y0 = sim(net,0) %számoljuk ki a háló válaszát a 0 helyen. y = sim(net,x); %számoljuk ki a háló válaszát az x vektor összes elemére figure; %nyissunk eg új grafikon ablakot plot(x,d,'b',x, y,'r'); %kékkel ábrázoljuk a tanítómintákat, pirossal a háló válaszát Nézzünk egy kicsit bonyolultabb beállítást. Sokszor előfordul, hogy mi magunknak szeretnénk tanítóés teszt mintahalmazt generálni. Fontos, hogy a minták legyenek összekeverve, hogy a bemeneti tér minden részén legyen tanító- és tesztmintánk is. len = size(x,2); %az x vektor második dimenzió mentén vett mérete, vagyis a hossza perm = randperm(len); %vesszük 1-től az x hosszáig lévő egész számoknak egy véletlen %permutációját trainlen = round(len*0.8); %a leendő tanító mintahalmazunk hossza, az összes minta 80%-a trainx = x(perm(1:trainlen)); %a perm vektor elejéről veszünk trainlen indexet, és vesszük az %ehhez tartozó x értékeket traind = d(perm(1:trainlen)); testx = x(perm(trainlen+1:end)); %vesszük az x vektor maradék elemeit testd = d(perm(trainlen+1:end)); 1
És ezzel a tanító és teszt mintahalmazzal a tanítás, sima egyszerű gradiens módszerrel: %MLP létrehozása, rejtett rétegben szigmoid kimeneti réteg lineáris, legegyszerűbb gradiens %eljárás net = newff(trainx,traind,15,{'tansig', 'purelin'},'traingd'); net.trainparam.lr = 0.1; net.trainparam.epochs = 2000; net.divideparam.testratio = 0; net.divideparam.valratio = 0; net.divideparam.trainratio = 1; net = train(net,trainx,traind); %bátorsági faktor (learning rate) %hányszor iteráljunk végig az összes tanítómintán %minden mintát tanításra használunk %tényleges tanítás plot(x,d,'b',testx,sim(net,testx),'rx'); %teszteljük a háló válaszát a tesztpontokban 1.2 RBF alkalmazása Az RBF hálónak a cos függvényt tanítjuk meg. Ehhez először generálunk tanító és teszt mintapontokat egy meghatározott tartományból. %tanito adat parameterek maxx = 4*pi; % vizsgálati tartomány felsö határa minx = -5*pi; % vizsgálati tartomány alsó határa trainnum = 300; % tanítási pontok száma testnum = 100; % tesztpontok száma noise = 0.1; % tanítási bemenetek x = [minx:(maxx-minx)/(trainnum-1):maxx]; x_t = [minx:(maxx-minx)/(testnum-1):maxx]; d = cos(x); d_t = cos(x_t); y = d + noise*2.0*(rand(1, trainnum)-0.5); Ezek után átparaméterezünk egy hagyományos MLP-t, hogy RBF-ként viselkedjen. Ehhez az első rétegbeli bázisfüggvényeket kell lecserélni radiálisra, a második rétegbelit pedig lineárisra. % hálóépítés neuronnum = 10; spread = 2; x0 = [minx:(maxx-minx)/(neuronnum-1):maxx]; % RBF neuronok 'középpontjai' %input, layern, offset, inputconn, layerconn, outputconn net = network(1,2,[1;1],[1;0],[0 0;1 0],[0 1]); % 1. (RBF) réteg net.inputs{1}.size = 1; %1D bemenet net.layers{1}.size = neuronnum; %1. retegbeli neuronok szama net.inputweights{1, 1}.weightFcn = 'dist'; %a bemenet elso retegbeli sulyoktol valo tavolsaga erdekes net.layers{1}.netinputfcn = 'netprod'; %a beallitott offsettel szorozni szeretnenk net.layers{1}.transferfcn = 'radbas'; %vegul vesszuk ennek az exp függvenyet net.b{1} = ones(neuronnum,1)*sqrt(-log(0.5))/spread; %a beallitott offset (szorasra van hatassal) net.iw{1, 1} = x0'; %kezdo bazisfv kozeppontok % 2. (összegzö) réteg (egy sima perceptron) net.layers{2}.size = 1; net.layers{2}.transferfcn = 'purelin'; net.b{2} = 2.0*(rand(1, 1)-0.5); %veletlen offset net.lw{2, 1} = 2.0*(rand(1, neuronnum)-0.5); %veletlen sulyok A tanítás paraméterei hasonlóak az MLP-nél látottakhoz. 2
% tanítási beállítások net.performfcn = 'mse'; net.trainfcn = 'trainlm'; net.inputweights{1}.learn = 0; net.biases{1}.learn = 0; net.trainparam.epochs = 1000; net.trainparam.goal = 1e-4; A tanítás és tesztelés (train, sim) is megegyezik. Az eredményeket egy ábrán jelenítjük meg. % tanítás [net] = train(net, x, y, [], []); %------------------------------------------------------------------------------- % a tanított háló kimenete out = sim(net, x_t); figure('name', 'tanított háló kimenete', 'position', [50, 450, 600, 400]); plot(x, y, 'g', x_t, d_t, 'b', x_t, out, 'r'); title('a háló kimenete tanítás után'); legend('tanító adatok', 'tesztadatok', 'tanított háló válasza'); 1.3 További módszerek További függvényapproximációs módszerként alkalmazhatunk SVM-et is, lásd később az idősor előrejelzés részben. 2 Osztályozás Az osztályozáshoz betöltjük az adatokat, kiválasztjuk a 2-5 dimenziókat, normalizálunk, keverünk és bontunk tanító, ill. tesztkészletre. clear all; load inputs.mat x y ids; %parameters %SVM toolbox %http://asi.insa-rouen.fr/enseignants/~arakotom/toolbox/index.html %mode = 'mlp'; mode = 'svm'; x = x(:,2:5); % normalization x = x - repmat(mean(x),size(x,1),1); x = x./ repmat(std(x),size(x,1),1); %performance measurement trainperf = 0; testperf = 0; tp = 0; fp = 0; tn = 0; fn = 0; %permutate samples mixer = randperm(size(x,1)); x(1:size(x,1),:) = x(mixer,:); y(1:size(y,1),:) = y(mixer,:); %separate train and test sets xtrain = x(1:floor(size(x,1)/2),:); ytrain = y(1:floor(size(x,1)/2),:); 3
xtest = x(floor(size(x,1)/2)+1:size(x,1),:); ytest = y(floor(size(x,1)/2)+1:size(x,1),:); Ha SVM-mel szeretnénk osztályozni, először be kell állítanunk néhány paramétert. %SVM mode if(strcmp(mode,'svm')) %svm parameters lambda = 1e-7; verbose = 0; %svm kernel parameter. %use poly with degree 1 for a linear kernel kernel='poly'; % kernel = 'gaussian'; % kernel = 'wavelet'; kerneloption = 1; c = 0.01; %compensate for the unbalanced training set costfactor = sum(ytrain < 0) / sum(ytrain > 0); C = ones(size(ytrain,1),1) * c; C(ytrain > 0) = c * costfactor; A tanításhoz és teszteléshez ezek után már elég 1-1 függvényt hívni. %learn [xsup,w,w0,pos,tps,alpha] = svmclass(xtrain,ytrain,c,lambda,kernel,kerneloption,verbose); %evaluate ytrainpred = svmval(xtrain,xsup,w,w0,kernel,kerneloption,1); ytestpred = svmval(xtest,xsup,w,w0,kernel,kerneloption,1); MLP használatához a már látott függvényeket használhatjuk. %MLP mode elseif(strcmp(mode,'mlp')) %mlp parameters MSE = 1e-5; Epochs = 3000; EpochsToShow = 1; NumLayer1Neurons = 20; end %create net net = newff(xtrain', ytrain', [NumLayer1Neurons], {'tansig', 'tansig'}, 'trainlm'); net.trainparam.epochs = Epochs; % max. hány ciklusban net.trainparam.goal = MSE; % mekkora hibánál álljon le net.trainparam.show = EpochsToShow; %train net = train(net, xtrain', ytrain'); %evaluate ytrainpredt = sim(net, xtrain'); ytestpredt = sim(net, xtest'); ytrainpred = ytrainpredt'; ytestpred = ytestpredt'; A kapott eredményeket MLP és SVM esetén is küszöböljük és összehasonlítjuk a várt kimenetekkel, amiből statisztikát készítünk. 4
%threshold predicted values ytrainpredth = ytrainpred > 0; ytrainpredth = (ytrainpredth-0.5)*2; ytestpredth = ytestpred > 0; ytestpredth = (ytestpredth-0.5)*2; %performance measurement %overall trainperf = trainperf + sum(ytrainpredth == ytrain) / size(ytrain,1) testperf = testperf + sum(ytestpredth == ytest) / size(ytest,1) %true positives tp = tp + sum(ytest == 1 & ytestpredth == 1) %false positives fp = fp + sum(ytest == -1 & ytestpredth == 1) %true negatives tn = tn + sum(ytest == -1 & ytestpredth == -1) %false negatives fn = fn + sum(ytest == 1 & ytestpredth == -1) 3 Idősor előrejelzés Az idősor előrejelzést egy egyszerű egydimenziós idősor példáján mutatjuk be. 3.1 SVM alkalmazása Az adatokat először az alkalmazott idősor modellnek megfelelő alakra kell hozni (azaz a mintapontokat az idősor elemeiből elő kell állítani). clear all; load 'food_train'; prediction_offset = 10; trainlength = 10; %preallocate for speed trainsetx = zeros(1100,trainlength); trainsety = zeros(1100,1); xtest = zeros(296-trainlength,trainlength); ytest = zeros(296-trainlength,1); %fill train data for i=1:1100 trainsetx(i,:) = x(i:i+trainlength-1)'; trainsety(i,1) = x(i+trainlength-1+prediction_offset); end for testi = 1:(296-trainlength) xtest(testi,:) = x(1100+testi:1100+testi+trainlength-1)'; ytest(testi,1) = x(1100+testi+trainlength-1+prediction_offset); end ttest = 1101+trainlength-1+prediction_offset : 1395+prediction_offset; Ezek után az SVM felparaméterezése és tanítása hasonlít az osztályozós esethez, leszámítva, hogy most a regresszióhoz használatos toolbox függvényeket használjuk. %svm parameters lambda = 1e-7; verbose = 0; %svm kernel parameter. %use poly with degree 1 for a linear kernel kernel='poly'; kerneloption = 1; c = 0.01; epsilon = 0.01; 5
%training [xsup,ysup,w,b] = svmreg(trainsetx, trainsety, c, epsilon, kernel, kerneloption, lambda, verbose); %test and measure performance predy = svmval(xtest,xsup,w,b,kernel,kerneloption); Az eredmények értékelhetők például az átlagos négyzetes hiba számításával. sqerr = (predy - ytest).^2 /(296-trainlength); figure, plot(t(1:1400),x(1:1400),'b',ttest,predy,'r'); 3.2 MLP alkalmazása A Matlabban van egy egyszerűbben használható, time-delay MLP implementáció is, melyet szintén használhatunk idősor előrejelzésre. clear all; load 'food_train'; prediction_offset = 10; trainlength = 10; x2 = x'; x2 = con2seq(x2); %hozzuk létre az MLP-t, az 1 bemenetet késleltessük 1..10 lépéssel, ezek %lesznek a tényleges bemenetek. 20 rejtett réteg beli neuront használunk net = newfftd(x2,x2, [1:trainlength], [20], {'tansig', 'purelin'}, 'trainlm'); Tanítsuk a hálót a szokásos train paranccsal: %hozzuk létre a tanítómintákat. A kívánt válasz megfelelő lépéssel %késleltetve van. p = x2(trainlength+1:end-prediction_offset+1); t = x2(prediction_offset+trainlength:end); Pi= x2(1:trainlength); %a késleltetett bemenetek inicializálásához kell net = train(net,p,t,pi); %a háló tanítása Majd ellenőrizzük a működését y = sim(net,p,pi);%ellenőrizzük a hálót y2 = seq2con(y); y2 = y2{1}; Pi2 = seq2con(pi); Pi2 = Pi2{1}; t2 = seq2con(t); t2 = t2{1}; figure; plot(t2,'b'); hold; plot(y2,'r');%ábrázoljuk grafikonon a kívánt választ és a tényleges választ 6