Progetto di sistemi intelligenti
Time Series Neural Network
Fabio Aiuto Federico Bianucci
Irene Bontà
1
Sommario Corali di Bach .................................................................................................................................................... 3
Obiettivi ........................................................................................................................................................ 3
Risoluzione .................................................................................................................................................... 4
Suddivisione dei dati ..................................................................................................................................... 7
Grafici .......................................................................................................................................................... 11
Advanced Script .......................................................................................................................................... 15
Dati significativi ........................................................................................................................................... 17
Osservazioni ................................................................................................................................................ 18
Cosa fare perciò? ........................................................................................................................................ 19
Predizione dei picchi di ozono nell’aria .......................................................................................................... 20
Obiettivi ...................................................................................................................................................... 20
Elaborazione dei dati .................................................................................................................................. 20
Addestramento ........................................................................................................................................... 23
Grafici .......................................................................................................................................................... 25
Osservazioni ................................................................................................................................................ 27
Conclusioni .................................................................................................................................................. 42
2
Indice delle figure
Figura 1 -‐ Importazione dati .............................................................................................................................. 4 Figura 2 -‐ Creazione delle variabili .................................................................................................................... 4 Figura 3 -‐ nnstart ............................................................................................................................................... 5 Figura 4 -‐ Rete NAR ........................................................................................................................................... 5 Figura 5 -‐ Selezione dei dati .............................................................................................................................. 6 Figura 6 -‐ Suddivisione dei dati ......................................................................................................................... 8 Figura 7 -‐ Training ............................................................................................................................................. 9 Figura 8 -‐ Addestramento della rete ............................................................................................................... 10 Figura 9 -‐ Grafico della Performance .............................................................................................................. 11 Figura 10 -‐ Grafico dell'autocorrelazione dell'errore ...................................................................................... 12 Figura 11 -‐ Grafico della risposta della serie storica ....................................................................................... 13 Figura 12 -‐ Istogramma dell'errore ................................................................................................................. 13 Figura 13 -‐ Grafico della regressione .............................................................................................................. 14 Figura 14 -‐ Rete neurale NAR in anello chiuso ................................................................................................ 16 Figura 15 -‐ Addestramento della nuova rete .................................................................................................. 18 Figura 16 -‐ Grafico della performance ............................................................................................................ 19 Figura 17 -‐ Rete neurale NARX ........................................................................................................................ 23 Figura 18 -‐ Addestramento della rete ............................................................................................................. 24 Figura 19 -‐ Grafico della performance ............................................................................................................ 25 Figura 20 -‐ Grafico dell'autocorrelazione dell'errore ...................................................................................... 26 Figura 21 -‐ Grafico della correlazione tra input e errore ................................................................................ 26 Figura 22 -‐ Addestramento della nuova rete .................................................................................................. 29 Figura 23 -‐ Grafico della performance ............................................................................................................ 30 Figura 24 -‐ Grafico dell'autocorrelazione dell'errore ...................................................................................... 31 Figura 25 -‐ Grafico della regressione .............................................................................................................. 31 Figura 26 -‐ Grafico della correlazione di input e errore .................................................................................. 33 Figura 27 -‐ Addestramento della rete finale ................................................................................................... 34 Figura 28 -‐ Grafico della performance ............................................................................................................ 35 Figura 29 -‐ Grafico dell'autocorrelazione ........................................................................................................ 36 Figura 30 -‐ Grafico della correlazione tra input e errore ................................................................................ 36 Figura 31 -‐ Rete NARX in anello chiuso con funzione di trasferimento lineare .............................................. 39 Figura 32 -‐ Valori reali predetti dalla rete ....................................................................................................... 40 Figura 33 -‐ Rete NARX in anello chiuso con funzione di trasferimento a soglia ............................................. 41 Figura 34 -‐ Grafico dei valori interi predetti dalla rete ................................................................................... 42
3
Corali di Bach
Obiettivi
Lo scopo del progetto è analizzare una serie storica e riuscire a creare una rete neurale, addestrarla e fare in modo che riesca a prevedere come tale serie debba continuare. Sul sito dell’UCI Machine Learning Repository abbiamo deciso di analizzare un dataset delle corali di Bach. Una corale è una serie di note in cui ogni nota presenta determinate caratteristiche. Il dataset in questione è formato da 100 corali, di cui per semplicità è stata codificata in formato Lisp la sola linea del soprano (originariamente le corali erano a 4 voci). Questo perché la singola linea melodica del soprano può essere studiata indipendentemente dalle altre voci. Con la serie in questione dovremo riuscire a creare una rete neurale che abbia capito le proprietà melodiche della corale e riesca a riprodurre note nuove che mantengono le caratteristiche musicali dell’intera corale. Verificheremo poi se la rete opportunamente addestrata abbia generato lavori originali e accettabili.
Ogni nota delle corali è codificata con 6 attributi:
a) Tempo di partenza, misurato in sedicesimi dall’inizio della corale (tempo 0). b) Tono, numero MIDI (60 = C4, 61 = C#4, 72 = C5, etc.). c) Durata, misurata in sedicesimi di nota. d) Chiave, numero di diesis o bemolle, positiva se la chiave ha dei diesis, negativa se
la chiave ha dei bemolle. e) Tempo, in sedicesimi per battuta. f) Corona, vero o falso, dipende se la nota sta sotto corona o no.
Il dominio di ogni attributo è il seguente:
a) {0,1,2,...} b) {60,...,75} c) {1,...,16} d) {-4,...,+4} e) {12,16} f) {0,1}
Non ci sono attributi con valori mancanti. Le sezioni ripetute (|: :|) non sono state codificate (per es. |:A:|B è stato codificato come AB).
4
Risoluzione
Per addestrare la nostra rete abbiamo scelto la corale numero 58 del dataset, composta da 86 elementi o note. Abbiamo importato la matrice 86x6 opportunamente costruita nel workspace di Matlab dal file chorales.txt. Il dataset originario era stato codificato in linguaggio Lisp, perciò, per importare la struttura in Matlab, abbiamo suddiviso ogni nota per ogni riga della matrice, mentre le colonne rappresentano i relativi attributi.
Figura 1 -‐ Importazione dati
Figura 2 -‐ Creazione delle variabili
5
Abbiamo quindi avviato il Neural Network Tool di Matlab con il comando nnstart.
Figura 3 -‐ nnstart
Di lì si è scelto di usare il Time Series mediante una rete neurale NAR (nonlinear autoregressive).
Figura 4 -‐ Rete NAR
6
Il nostro obiettivo è quello di predire valori futuri della serie utilizzando valori passati della serie stessa. Si utilizza una rete di tipo NAR, in quanto non sono presenti variabili esogene, per cui la predizione dell’uscita y(t) è data da d (nel nostro caso, come vedremo più avanti, 4) valori passati di y(t). Non esistono variabili esogene perché tutti gli attributi della serie in input sono attributi dei target e che quindi vogliamo necessariamente in uscita. Le variabili esogene, invece, sono per definizione variabili che influiscono sull’uscita della rete ma che non fanno parte del target.
Figura 5 -‐ Selezione dei dati
7
Suddivisione dei dati
Quando si addestrano reti multilayer, occorre innanzi tutto dividere i dati in 3 sottoinsiemi. Il primo sottoinsieme è il training set, che viene usato per calcolare il gradiente e aggiornare i pesi e i bias della rete. Ricordiamo che il processo di apprendimento può essere interpretato come una discesa lungo la linea di massima pendenza individuata appunto dal gradiente. La risposta fornita dalla rete per ogni esempio viene confrontata con la risposta desiderata (target), si valuta la differenza (errore) fra le due e, in base a tale differenza, si aggiustano i pesi. Questo processo viene ripetuto sull’intero training set finché le uscite della rete producono un errore al di sotto di una soglia prestabilita. Il secondo sottoinsieme è il validation set. L’errore sul validation set viene monitorato durante il processo di addestramento. L’errore di validazione normalmente diminuisce durante la fase di addestramento, così come l’errore sul training set. Tuttavia, quando la rete comincia ad andare in overfitting, l’errore sul validation set tipicamente comincia a salire. I pesi e i bias della rete vengono salvati al momento del minimo errore sul validation set. Tale valore anche se non è il minimo assoluto rappresenta comunque il minimo errore prima che la rete non riesca a generalizzare.
L’errore sul test set non viene usato durante l’addestramento della rete, ma viene usato per confrontare modelli diversi con i pesi già definiti. Se l’errore sul test set raggiunge un minimo ad un valore di iterazione significativamente diverso dall’errore sul validation set, questo può indicare una cattiva divisione dei dati. Infatti i due set di dati sono generalmente simili nel caso in cui i campioni scelti sono significativi.
8
I dati per la validazione e il test sono stati settati entrambi al 15% dei dati originali. Con queste impostazioni, i vettori di ingresso e target saranno casualmente divisi in 3 set:
ü Il 70% sarà usato per il training ü Il 15% sarà usato per validare la rete, ovvero per capire se la rete sta
generalizzando e quindi fermare il training prima di un overfitting ü Il restante 15% sarà usato per un test completamente indipendente sulla
generalizzazione della rete.
Figura 6 -‐ Suddivisione dei dati
9
La rete NAR che abbiamo creato è una rete a due livelli, con una funzione di trasferimento sigmoide nello strato nascosto e una funzione di trasferimento lineare nello strato di uscita. Il numero di default di neuroni nascosti è di 10, mentre il numero di default di ritardi è di 2, ma in questo caso lo abbiamo cambiato a 4 per migliorare le performance della rete. Così facendo l’uscita y(t) dipenderà dei valori della y(t) nei 4 istanti precedenti. Tale scelta è legata ad una motivazione strettamente musicale in quanto il tempo in chiave della corale è 4/4 indicando quindi una periodicità di base di 4 note.
Figura 7 -‐ Training
10
A questo punto abbiamo addestrato la rete. L’addestramento è durato 58 epoche dove un’epoca rappresenta un ciclo di presentazione degli esempi del training set. Dall’immagine si vede che l’addestramento è andato avanti finché l’errore sulla validazione non ha smesso di diminuire dopo 6 iterazioni (validation stop).
Figura 8 -‐ Addestramento della rete
Concluso l’addestramento, si passa all’analisi dei grafici.
11
Grafici
Il primo grafico che ci viene presentato è il grafico della performance del training, della validazione e del test.
Figura 9 -‐ Grafico della Performance
Questo grafico ci consente di controllare un potenziale overfitting. Dall’immagine si vede che gli errori di addestramento, validazione e test diminuiscono tutti fino all’iterazione 52, dopo la quale notiamo un incremento anche se minimo dell’errore sul validation set che indica che la rete non riesce, da quel momento in poi, a generalizzare. Vengono dunque congelati i pesi della rete ottenuti dal training set alla 52°epoca. Con tale pesi la rete dà un errore quadratico medio di 1,7544. L’aumento dell’errore sul validation set e la contemporanea diminuzione dell’errore sul training set ci indica in presenza di un possibile overfitting. Dal validation stop in poi le prestazioni sui dati di allenamento aumentano mentre le prestazioni sui dati di test sono peggiori.
12
Interessante è anche il grafico dell’autocorrelazione dell’errore. Esso descrive come gli errori di predizione sono correlati nel tempo con se stessi. Per un modello di predizione perfetto, bisognerebbe che ci fosse un solo valore non nullo in corrispondenza dello 0 (questo è l’errore quadratico medio). Vorrebbe dire che gli errori di predizione sono completamente scorrelati dagli altri. Il risultato ottenuto comunque è molto buono in quanto le correlazioni, eccetto quella in corrispondenza dello 0, cadono approssimativamente nell’intervallo di confidenza del 95%, tanto che si può dire che il modello è adeguato.
Figura 10 -‐ Grafico dell'autocorrelazione dell'errore
13
Il grafico, invece, della risposta della serie storica mostra gli input, i target e gli errori nel tempo. Esso indica anche quali punti e in quale momento sono stati selezionati per il training, il testing e la validazione.
Figura 11 -‐ Grafico della risposta della serie storica
Figura 12 -‐ Istogramma dell'errore
C’è poi il grafico dell’istogramma dell’errore che mostra il numero di volte in cui un certo valore dell’errore si presenta per i tre diversi tipi di set. Notiamo che con ci sono valori di errore significativamente lontani dall’errore nullo quindi tutte le epoche hanno prodotto un errore piuttosto basso.
Infine importantissimo è il grafico della regressione:
Figura 13 -‐ Grafico della regressione
Dal grafico emerge che il modello è molto buono. Le rette di regressione hanno tutte un coefficiente prossimo a 1 quindi la retta ideale si sovrappone alla retta ottenuta ad ogni prova. Tale retta minimizza la somma dei quadrati degli scarti. Non essendoci pallini estremamente lontani dalla retta vuol dire che per tutte le epoche si sono registrati degli errori piuttosto bassi.
15
Advanced Script
Di seguito abbiamo riportato lo script generato per addestrare e testare la nostra rete.
% Solve an Autoregression Time-Series Problem with a NAR Neural Network % Script generated by NTSTOOL % Created Mon Jan 10 23:45:58 CET 2011 % % This script assumes this variable is defined: % % chorales - feedback time series. targetSeries = tonndata(chorales,false,false); % Create a Nonlinear Autoregressive Network feedbackDelays = 1:4; hiddenLayerSize = 10; net = narnet(feedbackDelays,hiddenLayerSize); % Choose Feedback Pre/Post-Processing Functions % Settings for feedback input are automatically applied to feedback output % For a list of all processing functions type: help nnprocess net.inputs{1}.processFcns = {'removeconstantrows','mapminmax'}; % Prepare the Data for Training and Simulation % The function PREPARETS prepares timeseries data for a particular network, % shifting time by the minimum amount to fill input states and layer states. % Using PREPARETS allows you to keep your original time series data unchanged, while % easily customizing it for networks with differing numbers of delays, with % open loop or closed loop feedback modes. [inputs,inputStates,layerStates,targets] = preparets(net,{},{},targetSeries); % Setup Division of Data for Training, Validation, Testing % For a list of all data division functions type: help nndivide net.divideFcn = 'dividerand'; % Divide data randomly net.divideMode = 'time'; % Divide up every value net.divideParam.trainRatio = 70/100; net.divideParam.valRatio = 15/100; net.divideParam.testRatio = 15/100; % Choose a Training Function % For a list of all training functions type: help nntrain net.trainFcn = 'trainlm'; % Levenberg-Marquardt % Choose a Performance Function % For a list of all performance functions type: help nnperformance net.performFcn = 'mse'; % Mean squared error % Choose Plot Functions % For a list of all plot functions type: help nnplot net.plotFcns = {'plotperform','plottrainstate','plotresponse', ... 'ploterrcorr', 'plotinerrcorr'}; % Train the Network [net,tr] = train(net,inputs,targets,inputStates,layerStates);
16
% Test the Network outputs = net(inputs,inputStates,layerStates); errors = gsubtract(targets,outputs); performance = perform(net,targets,outputs) % Recalculate Training, Validation and Test Performance trainTargets = gmultiply(targets,tr.trainMask); valTargets = gmultiply(targets,tr.valMask); testTargets = gmultiply(targets,tr.testMask); trainPerformance = perform(net,trainTargets,outputs) valPerformance = perform(net,valTargets,outputs) testPerformance = perform(net,testTargets,outputs) % View the Network view(net) % Plots % Uncomment these lines to enable various plots. %figure, plotperform(tr) %figure, plottrainstate(tr) %figure, plotresponse(targets,outputs) %figure, ploterrcorr(errors) %figure, plotinerrcorr(inputs,errors) % Closed Loop Network % Use this network to do multi-step prediction. % The function CLOSELOOP replaces the feedback input with a direct % connection from the outout layer. netc = closeloop(net); [xc,xic,aic,tc] = preparets(netc,{},{},targetSeries); yc = netc(xc,xic,aic); perfc = perform(net,tc,yc)
view(netc)
Figura 14 -‐ Rete neurale NAR in anello chiuso
17
Dati significativi
Per trarre ulteriori conclusioni abbiamo riportato la struttura della nostra rete (net):
>> net net = Neural Network name: 'NAR Neural Network' efficiency: .cacheDelayedInputs, .flattenTime, .memoryReduction userdata: (your custom info) dimensions: numInputs: 1 numLayers: 2 numOutputs: 1 numInputDelays: 4 numLayerDelays: 0 numFeedbackDelays: 0 numWeightElements: 214 sampleTime: 1
Osservazioni
Abbiamo evidenziato come il numero di pesi è di 214. Quando abbiamo costruito la rete sapevamo che fosse necessario dimensionare lo strato nascosto affinché il rapporto pesi/dati fosse accettabile ovvero che i dati fossero almeno 5 volte più numerosi dei pesi.
A questo punto occorre considerare che la nostra serie è composta da soltanto 86 elementi, troppo pochi per pretendere che la rete apprenda bene il comportamento da tenere. A riprova di ciò ci viene incontro la struttura di yc, l’array di celle contenente la serie predetta. La predizione viene fatta quando la rete termina l’addestramento e vengono retroazionate le uscite. La rete a quel punto prevedrà valori di y(t) solo in base a valori precedentemente predetti. Analizzando il contenuto dell’array si nota che dal punto di vista prettamente musicale esso non ha alcun senso. La rete presenta infatti grafici che evidenziano un corretto addestramento ma nonostante ciò non riesce a generalizzare a causa dell’overfitting. Si potrebbe pensare di ridurre i pesi della rete attraverso la riduzione dei neuroni e di ritardi ma in questo modo l’errore aumenterebbe considerevolmente. Verifichiamo quanto detto facendo una prova: lasciamo inalterato il delay e diminuiamo a 8 i neuroni dello strato nascosto:
Figura 15 -‐ Addestramento della nuova rete
19
Figura 16 -‐ Grafico della performance
numWeightElements: 172
Il numero dei pesi è diminuito, ma il grafico della performance ci conferma quanto ci aspettavamo, cioè che i pesi della rete vengono congelati ad un'epoca in cui l’errore quadratico medio è aumentato (3,5406). E’ banale intuire che continuare a diminuire i neuroni dello strato nascosto porta ad un incremento dell’errore ed invece aggiungere neuroni comporterebbe un peggioramento della tendenza di overfitting e dunque predizioni senza senso.
Cosa fare perciò?
In alternativa, lasciando inalterati i pesi, occorrerebbe avere serie più lunghe, con un maggior numero di elementi. Abbiamo pensato di unire più corali insieme, ma data la grande differenza tra di esse, ancora una volta musicalmente ciò non avrebbe avuto senso.
In poche parole, predire musica nuova e originale da musica già esistente è un problema veramente complesso.
20
Predizione dei picchi di ozono nell’aria Obiettivi
Lo scopo del progetto è quello di analizzare una serie storica riguardante i livelli di ozono nell’aria. In particolare, il dataset originale, preso sul sito dell’UCI Machine Learning Repository, si riferisce alle rilevazioni giornaliere fatte dal 1998 al 2004 nelle zone di Galveston e Brazoria (Houston). Il lavoro prende spunto da una ricerca effettuata da alcuni studiosi, Forecasting skewed biased stochastic ozone days: analyses, solutions and beyond, Knowledge and Information Systems, e pubblicata nel 2008.
Vogliamo riuscire a predire quali saranno i possibili giorni in presenza di un picco di ozono nell’aria, addestrando la nostra rete a riconoscerli grazie alla variazione di alcuni fattori fondamentali.
Elaborazione dei dati
In questo secondo caso abbiamo a disposizione un numero ben più elevato di dati. Ciò ci permette di avere maggiori gradi di libertà nel cercare di addestrare correttamente la nostra rete neurale. La rete che vogliamo costruire dovrà riuscire a prevedere la presenza o meno di tasso di ozono nell’aria nei giorni successivi alle rilevazioni dei dati.
Il dataset originale è composto da 2536 istanze, ciascuna di 74 attributi. In particolare sono stati riportati I seguenti attributi:
ü attributo 1: data del rilevamento; ü attributi 2-25: velocità del vento ad ogni ora del giorno; ü attributi 26-27: velocità del vento massima e media giornaliera; ü attributi 28-51: temperatura ad ogni ora del giorno; ü attributi 52-53: temperatura massima e media giornaliera; ü attributi 54-58: temperatura, umidità, direzione del vento nord-sud, direzione del
vento est-ovest, altezza alla pressione di 85 mBar; ü attributi 59-63: temperatura, umidità, direzione del vento nord-sud, direzione del
vento est-ovest, altezza alla pressione di 70 mBar; ü attributi 64-68: temperatura, umidità, direzione del vento nord-sud, direzione del
vento est-ovest, altezza alla pressione di 50 mBar; ü attributo 69: ioduro di potassio; ü attributo 70: incognito; ü attributo 71: pressione al livello del mare; ü attributo 72: variante del precedente; ü attributo 73: livello delle precipitazioni. ü attributo 74: livello di ozono
21
Il dataset originale presenta al suo interno valori nulli, che sono stati codificati con il carattere '?'. Per far sì che tali valori potessero essere elaborati dalla nostra rete neurale, abbiamo scritto un semplice programma in C++ per sostituirli con la media tra il corrispondente valore precedente e valore successivo. Di seguito il codice:
#include <iostream> #include <fstream> #include <new> using namespace std;
int main() {
const int row=2000; const int col=73; char* a; double b=100000; ifstream is; is.open("dataset.txt"); if(is.fail()) {
cerr<<"Impossibile aprire il file."; return 1;
} ofstream os; os.open("dataset2.txt"); if(os.fail()) {
cerr<<"Impossibile aprire il file."; return 1;
} char* mat[row][col];
for(int i=0; i<row; i++) { for(int j=0; j<col; j++) {
is>>a; if (!strcmp(a,"?")) sprintf(a,"%g",b); mat[i][j]=a; os<<mat[i][j]<<"\t";
} os<<"\n";
} is.close(); os.close(); is.open("dataset2.txt"); if(is.fail()) {
cerr<<"Impossibile aprire il file."; return 1;
}
os.open("dataset3.txt"); if(os.fail()) {
cerr<<"Impossibile aprire il file."; return 1;
}
double cella; double media=0; double mat2[row][col]; system("PAUSE"); cout<<"\n"<<"\n";
22
for(int i=0; i<row; i++) {
for(int j=0; j<col; j++) { is>>cella; mat2[i][j]=cella;
} }
for(int i=0; i<row; i++) {
for(int j=0; j<col; j++) { if (mat2[i][j]==100000) {
int rigadown=i+1; while (mat2[rigadown][j]==100000)
rigadown++; media=(mat2[i-1][j]+mat2[rigadown][j])/2; mat2[i][j]=media;
} os<<mat2[i][j]<<"\t";
} os<<"\n";
} is.close(); os.close(); system("PAUSE"); return 0;
}
Il programma apre in lettura il dataset originale (dataset.txt) e in scrittura un file temporaneo (dataset2.txt).
Quindi riscrive il dataset originale nel file temporaneo, sostituendo al carattere '?' l'intero 100000 (valore non presente all'interno del dataset originale). A questo punto il programma apre il file temporaneo (dataset2.txt) in lettura e apre in scrittura il dataset definitivo (dataset3.txt), andando a sostituire ad ogni valore intero 100000 la media tra il corrispondente valore precedente e il corrispondente valore successivo, sempre che anche questo non sia un valore da modificare (in questo caso il programma scende al valore ancora successivo e così via).
Il dataset finale è formato da 2000 elementi, ciascuno composto da 73 attributi.
Ricordiamo che l’ultimo attributo di ciascuna rilevazione è per l’appunto il tasso di ozono presente nell’aria dunque il target della nostra rete. Esso rappresenta ciò che vogliamo prevedere e di conseguenza è fondamentale durante l’addestramento, perché i valori già noti di ozono ci consentono di calcolare la differenza tra ciò la rete produce e ciò che già conosciamo essere l’uscita desiderata. Abbiamo quindi stabilito che, tra tutti gli attributi, 72 (la data viene ignorata) influiscono indirettamente l’uscita della rete e perciò sono le variabili esogene in ingresso e solo il 73° esimo attributo è il target.
23
Addestramento
Per prima cosa scegliamo il tipo di rete che vogliamo creare: secondo quanto detto precedentemente la rete adatta al nostro caso è la rete NARX.
La prima prova che abbiamo voluto effettuare è di vedere il comportamento della rete secondo una struttura che prevede 10 neuroni nello strato nascosto e un delay pari a 2. Dunque durante l’addestramento verranno prodotto uscite y(t) che dipenderanno da y(t-1), da y(t-2), da x(t-1) e da x(t-2). La y(t) ottenuta verrà così confrontata con il target y(t) e verrà stabilito l’errore che la rete ha commesso. Terminato l’addestramento la rete calcolerà in maniera indipendente valori di y(t) che dipenderanno sempre da y(t-2), y(t-1), x(t-2) e x(t-1) ma stavolta le y non rappresentano i target bensì predizioni della rete che vengono retroazionati in ingresso alla rete stessa.
Figura 17 -‐ Rete neurale NARX
24
Per quanto riguarda la suddivisione dei dati abbiamo lasciato inalterate le percentuali di default che prevedono l’utilizzo del 75% per il training set, 15% per il validation set e il 15% per il test set.
Figura 18 -‐ Addestramento della rete
25
Grafici
Figura 19 -‐ Grafico della performance
Dall’immagine si vede che la rete completa velocemente il processo di addestramento. Gli errori di training, validazione e test diminuiscono tutti fino all’iterazione 2, dopo la quale notiamo un incremento dell’errore sul validation set, che indica che la rete non riesce, da quel momento in poi, a generalizzare. Vengono dunque congelati i pesi della rete ottenuti dal training set alla 2°epoca. Con tali pesi la rete dà un errore quadratico medio di 0,0466. Essendo il target formato da valori zero oppure uno, l’errore ottenuto è dell’ordine di grandezza del 5%, quindi concludiamo che è molto basso. E’ importante notare come la curva del test set sembra che nel tempo raggiunga alti valori dell’errore quadratico medio: tale comportamento era da noi preventivato, in quanto la rete ha un elevato numero di neuroni nello strato nascosto, per cui non vi è un buon rapporto tra dati e pesi della rete. Un sovradimensionamento della rete non implica necessariamente overfitting, ma in questo caso sembra proprio essersi verificato.
26
Figura 20 -‐ Grafico dell'autocorrelazione dell'errore
Interessante è anche il grafico dell’autocorrelazione dell’errore. Esso descrive come gli errori sono correlati nel tempo. Per un modello di predizione perfetto, bisognerebbe che ci fosse un solo valore non nullo in corrispondenza dello 0 (questo è l’errore quadratico medio). Vorrebbe dire che gli errori di predizione sono completamente scorrelati dagli altri. Il risultato ottenuto comunque è molto buono, in quanto le correlazioni, eccetto quella in corrispondenza dello 0, cadono approssimativamente nell’intervallo di confidenza, tanto che si può dire che il modello è adeguato.
Figura 21 -‐ Grafico della correlazione tra input e errore
Questo grafico mostra come gli errori sono correlati con la sequenza di input x(t). Per un modello perfetto di predizioni tutte le correlazioni dovrebbero essere 0. Nel nostro caso l’input è correlato con l’errore ma comunque tutte le correlazioni cadono all’interno dell’intervallo di confidenza.
27
Osservazioni
L’addestramento che abbiamo effettuato ci fornisce valutazioni positive in quanto la rete riesce ad imparare con un errore basso ed i grafici ci confermano che il modello è abbastanza buono. Dal grafico della performance abbiamo però individuato dell’overfitting suggeritoci dall’errore sul test set. Come precedentemente detto osserviamo che, con il numero di neuroni e delay scelti, la rete è sovradimensionata cioè abbiamo un rapporto pesi/dati troppo alto. I dati sono 2000, numWeightElements: 1481 quindi il rapporto è inferiore a 5.
net = Neural Network name: 'NARX Neural Network' efficiency: .cacheDelayedInputs, .flattenTime, .memoryReduction userdata: (your custom info) dimensions: numInputs: 2 numLayers: 2 numOutputs: 1 numInputDelays: 2 numLayerDelays: 0 numFeedbackDelays: 0 numWeightElements: 1481 sampleTime: 1
Detto ciò decidiamo di ridimensionare la rete e valutare se questo comporterà un miglioramento o peggioramento del processo di addestramento.
Innanzitutto abbiamo deciso di aumentare il numero di neuroni nascosti da 10 a 12.
Inoltre abbiamo pensato di diminuire il numero di variabili esogene, cercando di scegliere solamente quelle fondamentali. Ad ogni attributo infatti corrisponde una variabile esogena e ci sono alcuni attributi che influiscono maggiormente sull’uscita della rete piuttosto che altri, che sono poco rilevanti e che semplicemente sovradimensionano la rete. Leggendo la documentazione sul dataset abbiamo trovato riscontro in questa nostra ipotesi, quando troviamo infatti scritto:
“… only about 10 features among these 72 features have been verified by environmental scientists to be useful and relevant, and there is neither empirical nor theoretical information as of yet on the relevance of the other 60 features.”
28
Sempre studiando la documentazione siamo riusciti a circoscrivere un numero ristretto di variabili ritenute da noi fondamentali, associandole a quelle contenute nella formula che il sistema di forecasting descritto utilizza.
“… The following equation summarizes the parametric equation and the parameters involved.
EmFactor × (Tmax − Tb) × SRd
O3 = Upwind + --------------------------------------------- WSa × 0.1 +WSp × 0.5+ 1
in which,
ü O3 - Local ozone peak prediction ü Upwind - Upwind ozone background level ü EmFactor - Precursor emissions related factor ü Tmax - Maximum temperature in degrees F ü Tb - Base temperature where net ozone production begins (50 F) ü SRd - Solar radiation total for the day ü WSa - Wind speed near sunrise (using 09-12 UTC forecast mode) ü WSp - Wind speed mid-day (using 15-21 UTC forecast mode)”
Descriviamo brevemente le associazioni:
ü La variabile O3 è la variabile di uscita dal nostro sistema; ü La variabile Upwind è stata associata alla direzione del vento al livello più vicino a
quello del mare, perciò con le variabile del dataset U85 e V85; ü La variabile EmFactor non è altro che il livello di ozono del giorno precedente,
perciò è la nostra variabile di uscita in anello chiuso; ü La variabile Tmax è stata associata alla variabile del dataset con lo stesso
significato T_PK; ü La variabile Tb è stata associata alla variabile del dataset T_AV, che rappresenta la
temperatura media giornaliera; ü La variabile SRd non ha trovato associazioni nel dataset; ü La variabile WSa è stata associata alle variabili WSR9, WSR10, WSR11 e WSR12,
che indicano la velocità del vento dalle ore 9 alle ore 12; ü La variabile WSp è stata associata alle variabili WSR15, WSR16, WSR 17, WSR18,
WSR19, WSR20 e WSR21, che indicano la velocità del vento dalle ore 15 alle ore 21.
Abbiamo ridotto cosi il vettore delle variabili esogene da un vettore di dimensione 72 ad un vettore di dimensione 15.
29
Proseguiamo quindi con l’addestramento della nuova rete neurale.
I dati sono presi dal file “ozono_final.mat” che comprende gli input (dataset3) ed i target (ozoneTarget).
Figura 22 -‐ Addestramento della nuova rete
30
Figura 23 -‐ Grafico della performance
In questo grafico notiamo che l’addestramento è durato 10 epoche ma la presenza del validation set ci permette di congelare i pesi della rete alla 4°epoca per evitare l’overfitting della rete. L’errore quadratico medio ottenuto a tale epoca è comunque abbastanza piccolo (0,060706) e ciò ci fa pensare che la rete abbia imparato bene. In realtà l’aumento dell’errore sul validation set e la contemporanea diminuzione dell’errore sul training set ci indica in presenza di un possibile overfitting. Dal validation stop in poi le prestazioni sui dati di allenamento aumentano mentre le prestazioni sui dati di test sono peggiori.
Figura 24 -‐ Grafico dell'autocorrelazione dell'errore
Anche in questo caso la rete dà un grafico dell’autocorrelazione abbastanza buono evidenziando la bontà del modello.
Sarebbe importante valutare anche il grafico della regressione, ma in questo caso notiamo che non è significativo in quanto le uscite sono numeri reali e manca quindi una classificazione che le identifichi come zero oppure uno.
Figura 25 -‐ Grafico della regressione
32
net = Neural Network name: 'NARX Neural Network' efficiency: .cacheDelayedInputs, .flattenTime, .memoryReduction userdata: (your custom info) dimensions: numInputs: 2 numLayers: 2 numOutputs: 1 numInputDelays: 2 numLayerDelays: 0 numFeedbackDelays: 0 numWeightElements: 409 sampleTime: 1
La rete che abbiamo ottenuto sembra essere stata dimensionata in maniera opportuna. Abbiamo ottenuto un numero di pesi (409) all’incirca cinque volte inferiore ai dati di ingresso (2000). Dai grafici che abbiamo analizzato abbiamo verificato la bontà della rete che in poche epoche riesce ad apprendere con un errore quadratico medio piuttosto basso e con scarsa correlazione tra errori relativi a predizioni diverse.
Un aspetto fondamentale che ci rimane da valutare è quello di capire se ci sono input x(t) che sono maggiormente correlati con l’errore della rete. In caso di forti correlazioni dovremo aggiustare la rete variando i ritardi, facendo dunque in modo che l’errore di una predizione dipenda da un numero maggiore di variabili esogene.
33
Figura 26 -‐ Grafico della correlazione di input e errore
Dal grafico si vede che ci sono intervalli per cui la correlazione tra input ed errore è elevata, ben oltre il limite di confidenza. Nella nostra rete una predizione y(t) dipende dai target y(t-1),y(t-2) e dagli input x(t-1),x(t-2). La nostra idea è quella di aumentare il numero di ritardi per cercare di far dipendere l’errore da una porzione più ampia di ingressi e quindi scorrelare l’errore dai soli due ritardi.
34
Decidiamo perciò di fare un’ulteriore prova di addestramento utilizzando sempre 12 neuroni nascosti ma stavolta 4 ritardi in questo modo l’uscita y(t) dipenderà da y(t-1), y(t-2), y(t-3), y(t-4) e da x(t-1), x(t-2), x(t-3), x(t-4). Ci aspettiamo che la rete abbia un numero di pesi maggiore del caso precedente ma una minore correlazione tra input ed errore.
Figura 27 -‐ Addestramento della rete finale
35
Figura 28 -‐ Grafico della performance
In questo caso notiamo un leggero aumento dell’errore quadratico medio (0.078395). L’addestramento dura 29 epoche ma alla 23° epoca vengono congelati i pesi perché da quel momento in poi vi è un progressivo aumento dell’errore sul validation set quindi un possibile overfitting. Aspetto importante del grafico è il test set che sembra essere stato positivo, cioè ci dice che la rete in breve tempo raggiunge bassi errori di predizione e nel tempo si mantiene sempre con valori di errore piuttosto bassi. Dunque ci viene da pensare che il processo di addestramento è riuscito ad insegnare alla rete a generalizzare per cui avremo una predizione molto accurata.
36
Figura 29 -‐ Grafico dell'autocorrelazione
Anche in questo caso c’è scarsa correlazione tra l’errore di una predizione e gli errori su predizioni precedenti. Sono pochissimi gli istogrammi al di sopra della soglia di confidenza e perciò possiamo ritenerli poco significativi.
Figura 30 -‐ Grafico della correlazione tra input e errore
Adesso il grafico della correlazione tra input ed errore è decisamente migliore. Solo al valore di ascissa 0 abbiamo un picco della correlazione, ma è quello che ci aspettavamo. Per il resto notiamo che la scelta del numero di ritardi sugli ingressi sembra sia stata ottima: tutti i valori di correlazione sono dentro l’intervallo di confidenza.
37
net = Neural Network name: 'NARX Neural Network' efficiency: .cacheDelayedInputs, .flattenTime, .memoryReduction userdata: (your custom info) dimensions: numInputs: 2 numLayers: 2 numOutputs: 1 numInputDelays: 4 numLayerDelays: 0 numFeedbackDelays: 0 numWeightElements: 793 sampleTime: 1
Con questa ultima prova di addestramento della nostra rete possiamo ritenerci soddisfatti. La rete è ben dimensionata; riesce ad imparare con un errore quadratico medio abbastanza buono, anche se l’addestramento si interrompe per un validation stop in realtà vediamo che il test ci dimostra che la rete si mantiene su livelli di apprendimento buoni.
Di seguito riportiamo lo script che esegue Matlab per l’addestramento e la predizione della nostra rete neurale:
% Solve an Autoregression Problem with External Input with a NARX Neural Network % Script generated by NTSTOOL % Created Tue Jan 11 10:13:16 CET 2011 % % This script assumes these variables are defined: % % dataset3 - input time series. % ozono - feedback time series. inputSeries = tonndata(dataset3,false,false); targetSeries = tonndata(ozono,false,false); % Create a Nonlinear Autoregressive Network with External Input inputDelays = 1:4; feedbackDelays = 1:4; hiddenLayerSize = 12; net = narxnet(inputDelays,feedbackDelays,hiddenLayerSize); % Choose Input and Feedback Pre/Post-Processing Functions
38
% Settings for feedback input are automatically applied to feedback output % For a list of all processing functions type: help nnprocess % Customize input parameters at: net.inputs{i}.processParam % Customize output parameters at: net.outputs{i}.processParam net.inputs{1}.processFcns = {'removeconstantrows','mapminmax'}; net.inputs{2}.processFcns = {'removeconstantrows','mapminmax'}; % Prepare the Data for Training and Simulation % The function PREPARETS prepares timeseries data for a particular network, % shifting time by the minimum amount to fill input states and layer states. % Using PREPARETS allows you to keep your original time series data unchanged, while % easily customizing it for networks with differing numbers of delays, with % open loop or closed loop feedback modes. [inputs,inputStates,layerStates,targets] = preparets(net,inputSeries,{},targetSeries); % Setup Division of Data for Training, Validation, Testing % The function DIVIDERAND randomly assigns target values to training, % validation and test sets during training. % For a list of all data division functions type: help nndivide net.divideFcn = 'dividerand'; % Divide data randomly % The property DIVIDEMODE set to TIMESTEP means that targets are divided % into training, validation and test sets according to timesteps. % For a list of data division modes type: help nntype_data_division_mode net.divideMode = 'value'; % Divide up every value net.divideParam.trainRatio = 70/100; net.divideParam.valRatio = 15/100; net.divideParam.testRatio = 15/100; % Choose a Training Function % For a list of all training functions type: help nntrain % Customize training parameters at: net.trainParam net.trainFcn = 'trainlm'; % Levenberg-Marquardt % Choose a Performance Function % For a list of all performance functions type: help nnperformance % Customize performance parameters at: net.performParam net.performFcn = 'mse'; % Mean squared error % Choose Plot Functions % For a list of all plot functions type: help nnplot % Customize plot parameters at: net.plotParam net.plotFcns = {'plotperform','plottrainstate','plotresponse', ... 'ploterrcorr', 'plotinerrcorr'}; % Train the Network [net,tr] = train(net,inputs,targets,inputStates,layerStates); % Test the Network outputs = net(inputs,inputStates,layerStates); errors = gsubtract(targets,outputs); performance = perform(net,targets,outputs) % Recalculate Training, Validation and Test Performance trainTargets = gmultiply(targets,tr.trainMask); valTargets = gmultiply(targets,tr.valMask); testTargets = gmultiply(targets,tr.testMask); trainPerformance = perform(net,trainTargets,outputs)
39
valPerformance = perform(net,valTargets,outputs) testPerformance = perform(net,testTargets,outputs) % View the Network view(net) % Plots % Uncomment these lines to enable various plots. %figure, plotperform(tr) %figure, plottrainstate(tr) %figure, plotregression(targets,outputs) %figure, plotresponse(targets,outputs) %figure, ploterrcorr(errors) %figure, plotinerrcorr(inputs,errors) % Closed Loop Network % Use this network to do multi-step prediction. % The function CLOSELOOP replaces the feedback input with a direct % connection from the outout layer. netc = closeloop(net); netc.name = [net.name ' - Closed Loop']; view(netc) [xc,xic,aic,tc] = preparets(netc,inputSeries,{},targetSeries); yc = netc(xc,xic,aic); closedLoopPerformance = perform(netc,tc,yc) plot(cell2mat(yc),'bo')
Figura 31 -‐ Rete NARX in anello chiuso con funzione di trasferimento lineare
40
I valori predetti dalla rete, in questo caso, sono valori reali. Il grafico stampato dallo script è il seguente:
Figura 32 -‐ Valori reali predetti dalla rete
Per ottenere in uscita dalla rete valori di ozono interi, abbiamo utilizzato nello strato di uscita la funzione a soglia hardlims, messa a disposizione dalla libreria di Matlab. Poiché per tale funzione però la soglia di discriminazione è 0, abbiamo modificato il bias (ovvero l’inverso della soglia) della rete in anello chiuso con il valore 0.3.
In questo modo otteniamo in uscita dalla rete valori di ozono interi (0 o 1) discriminati da una soglia a 0.3. Abbiamo scelto 0.3 perché, come si vede dal grafico, la maggior parte dei valori sta sotto questa soglia, mentre i valori superiori sono picchi, ovvero valori non nella norma e quindi rappresentativi di un’alta presenza di ozono nell’aria.
41
La rete in anello chiuso con la nuova funzione a soglia si presenta in questo modo:
Figura 33 -‐ Rete NARX in anello chiuso con funzione di trasferimento a soglia
Lo script script_ozono.m calcola le uscite in anello chiuso:
inputSeries = tonndata(dataset3,false,false); targetSeries = tonndata(ozono,false,false); netc = closeloop(net); netc.b{2} = -0.3; netc.layers{2}.transferFcn = 'hardlims'; netc.name = [net.name ' - Closed Loop']; view(netc) [xc,xic,aic,tc] = preparets(netc,inputSeries,{},targetSeries); yc = netc(xc,xic,aic); closedLoopPerformance = perform(netc,tc,yc) plot(cell2mat(yc),'bo') figure plot(cell2mat(tc),’go’)
42
Conclusioni
A questo punto andiamo a valutare le previsioni fatte dalla nostra rete, plottando l’array di celle yc, che contiene I valori di ozono presenti nell’aria che la rete ha previsto.
Figura 34 -‐ Grafico dei valori interi predetti dalla rete
43
Figura 35 -‐ Grafico della serie dei target
Dall’analisi dei grafici possiamo dedurre che i valori predetti sono attendibili. La presenza di picchi di ozono nel grafico dei valori predetti è molto simile a quella del grafico della serie dei target. Questo significa che la rete ha appreso bene e riesce a dare in fase di esecuzione gli stessi risultati forniti in fase di addestramento.
In un futuro, se verranno presentati in ingresso alla rete nuovi valori, possiamo ragionevolmente pensare che la rete darà in uscita delle previsioni attendibili.