• Non ci sono risultati.

Gestione degli Algoritmi di Apprendimento

3.3 Librerie Usate

4.1.4 Gestione degli Algoritmi di Apprendimento

Una volta istanziato un modello, `e possibile passarlo ad un algoritmo di apprendimento per eseguire l’addestramento.

Anche in questo caso si `e ricorsi all’uso di un’abstract factory LearningAlgorithm- sFactory, la cui invocazione della funzione makeConcreteInstance restituisce l’istanza dell’algoritmo appropriata, in base a quanto descritto nel DescriptorParameter passato:

Listing 4.22: Creazione dell’Algoritmo di Apprendimento

LearningAlgorithmsFactory laf; iLearningAlgorithm* learning;

learning= laf.makeConcreteInstance(descriptor->

learningAlgorithmParameters, trainingset, validationset, model);

Oltre all’istanza del modello, l’algoritmo di apprendimento necessita, a tempo di crea- zione, delle istanze del training e validation set, necessari per effettuare l’addestramen- to.

La classe astratta iLearningAlgorithm contiene le principali funzionalit`a comuni a tutti gli algoritmi di apprendimento. Ad esempio, una volta istanziato l’algoritmo di apprendimento, per far partire l’addestramento `e sufficiente invocare la funzione start training:

Listing 4.23: Esecuzione del Training

learning->start_training();

Il risultato dell’addestramento pu`o essere prelevato dall’istanza results della classe Result (per i dettagli vedere Sez. 4.1.5) presente all’interno dell’istanza dell’algoritmo. Le seguenti righe di codice, ad esempio, stampano il risultato finale dell’addestra- mento:

4.1 Libreria felix 69

learning->start_training(); /// now the training is over

Result* results = learning->results;

std::cout<< "Training terminated, stop criteria met: "

<< results->finalStopCriteria << endl << "\tFinal Training Result: " << endl

<< "\t\t" << results->lastTrainingResults->str() << endl << "\tFinal Validaiton Result: " << endl

<< "\t\t" << results->lastValidationResults->str() << endl;

il risultato a video di queste righe di codice comprende un numero maggiore di infor- mazioni rispetto a quanto visto in Sez. 4.1.1, ed `e il seguente:

Listing 4.25: Stampa a Video Relativa al Codice Precedente

Training terminated, stop criteria met: Current MaxAbsError is equals or lesser than the mimimum one (0.0480365<=0.05)

Final Training Result:

MaE=0.013672 MaxAE=0.0480365 R=0.999386 S=0.0176099 Final Validaiton Result:

MaE=0.0186312 MaxAE=0.0533141 R=0.996919 S=0.0240095

Come `e possibile osservare, il codice espresso sopra `e indipendente dal tipo di modello, di algoritmo di apprendimento e tipo di dataset usato. Usando la struttura polimorfica della libreria, la creazione del modello, lo svolgimento dell’addestramento e la raccolta e stampa dei risultati si adatter`a a seconda del task, e del tipo di modello e algoritmo di apprendimento scelto, mediante il descrittore.

Tutti gli algoritmi di apprendimento implementati in felix sono sottoclassi concre- te di iLearningAlgorithm e sono stati implementati, a partire delle loro formulazioni teoriche5, nelle seguenti classi:

Backpropagation descritto in Sez. 2.2.1.1; Resilientpropagation descritto in Sez. 2.2.1.2; Quickpropagation descritto in Sez. 2.2.1.3;

Pseudoinverse descritto in Sez. 2.2.2.1, utilizzabile solo per l’addestramento delle unit`a di uscita;

5Fa eccezione il caso della pseudoinversa, dove ci siamo appoggiati alla libreria armadillo per il

CascadeCorrelation descritto in Sez. 2.3.1; CascadeResidual descritto in Sez. 2.3.2;

La funzione astratta start training possiede un’implementazione in iLearningAlgorithm che viene usata da tutti gli algoritmi di discesa del gradiente, la quale prevede di:

1. calcolare l’errore residuo per ogni pattern del training set;

2. aggiornare, usando l’errore residuo, il valore delle derivate parziali contenute in tutte le istanze weight delle unit`a, mediante la funzione updateAllDerivateValues; 3. modificare il valore dei pesi, ad epoca finita, invocando la funzione astratta

trainUnit su tutte le unit`a del modello;

4. controllare il soddisfacimento di eventuali stop criteria e, in caso negativo, tornare al punto 1;

La funzione di modifica dei pesi invocata all’interno della funzione astratta trainUnit `e praticamente l’unica che viene sovrascritta dalle classi che implementano i metodi del gradiente.

Ognuno di questi metodi differiscono solo dal modo in cui usano l’informazione sulla derivata parziale per aggiornare i pesi. Con questa organizzazione `e stato possibile implementare un metodo del gradiente scrivendo unicamente la sua funzione di modifica dei pesi, ereditando tutto il resto da iLearningAlgorithm.

La funzione start training viene, invece, sovrascritta per i metodi costruttivi, e lancia un’eccezione qualora la si invochi su un’istanza di Pseudoinverse.

Entrambi i metodi costruttivi implementati fanno uso di una struttura ausiliaria poolCandidate che permette l’addestramento di un’unit`a candidata in modo parallelo ed indipendente dalle altre. Per farlo, si `e ricorsi alla programmazione concorrente mediante l’uso di thread che effettuano l’addestramento concorrente di tutte le unit`a candidate, sfruttando il fatto che durante l’addestramento dell’unit`a candidata tutti gli altri pesi del modello sono congelati, caratteristica comune ad entrambe le varianti di algoritmi costruttivi viste.

Oltre a quanto detto, gli algoritmi di apprendimento hanno la possibilit`a di conser- vare all’interno dell’istanza results un log analitico dell’andamento dell’addestramen- to, in modo che possa essere analizzato successivamente (vedere Sez. 4.3.2). Que- sta opzione prevede, specialmente per training molto lunghi, un incremento notevo-

4.1 Libreria felix 71

le delle dimensioni del pacchetto dei risultati finali (vedere Sez. 4.1.5). Per que- sto motivo `e possibile escludere le funzionalit`a di logging settando a False l’attributo saveExtendedLogging del tag Learning del descrittore.

4.1.4.1 Stop Criteria

I vari stop criteria usati negli algoritmi di apprendimento sono creati nel costruttore di iLearningAlgorithm usando l’abstract factory StopCriteriaFactory.

Tra le classi che implementano i diversi stop criteria, abbiamo:

SC maxIterationReached che risulta soddisfatto al raggiungimento di una certa epoca massima, o di una certa unit`a nascosta, nel caso di algoritmi costrutti- vi. A seconda dei parametri passati, la soglia limite pu`o essere incrementata dinamicamente, permettendo di eseguire un’incremental strategy;

SC minimumMaximumAbsError che risulta soddisfatto al raggiungimento di un M axAbsE minimo fissato;

SC maximumTrainingResult che risulta soddisfatto al raggiungimento di un mas- simo valore dipendente dal task, come l’accuracy nel caso di classificazione; SC resultsStale che risulta soddisfatto al raggiungimento di uno stallo nel risultato; SC resultsMonotony che termina l’addestramento quando il risultato non mantie-

ne un andamento monotono;

SC minIterations questo controllo inibisce gli altri stop criteria, e permette di non fermare l’addestramento fino a che un numero minimo di epoche non sono passate, o un certo numero di unit`a nascoste non sono state create; Questo, pur non essendo un vero e proprio stop criteria, `e stato implementato come tale per facilit`a di integrazione;

Ognuna di queste classi `e una sottoclasse concreta della classe astratta Stop Criteria, ed implementa la funzione astratta pura isMet, invocata dall’algoritmo di apprendimento su ogni stop criteria che possiede. Di fatto, l’algoritmo di apprendimento non istanzia esplicitamente gli stop criteria, ma usando un’oggetto StopCriteriaFactory riempie un vettore di stop criteria posseduto localmente:

vector<StopCriteria*> stopCriteriaSet;

i cui elementi vengono controllati invocando isMet alla fine di ogni epoca.