3.3 Librerie Usate
4.1.3 Gestione dei Modelli
La libreria implementa due tipi di reti neurali usate per la gestione di dati flat e grafi, fornendo le relative istanze in modo analogo a quanto visto nei dataset.
Una classe astratta iNeuralNet implementa le interfacce comuni alle due sottoclassi concrete MultiLayerPerceptron e NN4G. Analogamente a quanto visto nella gestione dei dataset, `e presente una classe ModelsFactory che implmenta l’abstract factory usata per istanziare il modello. Anche in questo caso il modello pu`o essere istanziato mediante l’uso del descrittore:
Listing 4.13: Creazione del Modello Mediante il Descrittore
DatasetFactory mf;
iNeuralNet* model = mf.makeConcreteInstance(descriptor->dataParameters , dataset);
o caricandolo direttamente da file, ad esempio il file saved model.xml presente nella directory corrente:
4.1 Libreria felix 65
Listing 4.14: Caricamento del Modello da File
DatasetFactory mf;
iNeuralNet* model=mf.makeConcreteInstance("saved_model.xml");
Nel primo caso, `e necessario passare all’abstract factory anche un’istanza del dataset su cui il modello dovr`a operare. Questa istanza serve unicamente a fornire alcune informazioni dei dati al modello, come la cardinalit`a delle features e dei valori target, nel caso del NN4G.
La classe iNeuralNet racchiude le informazioni strutturali della rete neurale all’in- terno di due vettori pubblici, uno contente i layers:
Listing 4.15: Matrice dei Layer
vector<vector<iNeuralUnit*>* > layers;
ed uno contente le unit`a di uscita:
Listing 4.16: Vettore delle Unit`a di Uscita
vector<iNeuralUnit*> outputs;
La visibilit`a pubblica di queste strutture garantisce la massima flessibilit`a da parte dell’algoritmo di apprendimento, specialmente nel caso di algoritmi costruttivi che agiscono direttamente sull’archittettura della rete.
Tra le funzioni comuni pi`u importanti di questa classe troviamo: createNewUnit che restituisce una nuova unit`a pronta ad essere aggiunta alla rete da un algoritmo costruttivo, o la funzione save che permette di salvare il modello su file. La funzione di utilit`a makeIterator permette di creare un iteratore sulle unit`a del modello. Utile nel caso si voglia effettuare lo stesso tipo di operazione su tutte le unit`a della rete, come l’aggiornamento del valore dei pesi all’interno dei metodi del gradiente:
Listing 4.17: Esempio di Uso dell’Iteratore delle Unit`a di un Modello
iNeuralUnit* currentUnit;
UnitsIterator iter = model->makeIterator();
while(iter.hasNext()){
currentUnit = iter.next();
if(!currentUnit->frozen){ trainUnit(currentUnit,true); }
}
Ogni sottoclasse concreta di iNeuralNet deve implementare la funzione virtuale pura input che viene invocata quando si vuole conoscere la risposta del modello ad un pattern.
Dopo che la funzione viene invocata, la risposta del modello viene conservata nel vettore4 pubblico
Listing 4.18: Vettore dei Valori di Uscita del Modello
vector<double> results;
Ad esempio, il codice seguente stampa a video la risposta del modello model (assunto ad output singolo) a tutti i pattern presenti in dataset :
Listing 4.19: Esempio di Stampa della Risposta del Modello for(unsigned int i=0; i<dataset->size(); ++i){
model->input(dataset->at(i)); cout << model->results[0] << endl; }
4.1.3.1 Gestione delle Unit`a
La classe astratta iNeuralUnit rappresenta la singola unit`a della rete neurale ed imple- menta le funzionalit`a comuni alle sottoclassi concrete Perceptron e NN4GUnit usate, rispettivamente nelle classi MultiLayerPerceptron e NN4G. A seconda del tipo di rete neurale usata, il tipo effettivo delle unit`a contenute nei vettori layers e outputs sar`a relativo ad una delle due sottoclassi concrete di iNeuralUnit.
La funzione createNewUnit di iNeuralUnit permette agli algoritmi di apprendimen- to di generare unit`a del tipo effettivo corretto, senza dover conoscere il tipo di rete su cui stanno operando. Quando un algoritmo costruttivo necessita di una nuova unit`a, invoca createNewUnit sul modello
Listing 4.20: Esempio di Creazione di una Nuova Unit`a
iNeuralUnit* currentUnit = model->createNewUnit(iNeuralUnit::Hidden);
4.1 Libreria felix 67
il quale restituisce l’unit`a del tipo effettivo appropriato, copiandola da un’unit`a tem- plate, esterna alla rete, generata a tempo di creazione del modello.
Il calcolo dell’uscita del modello avviene chiamando, dall’interno della funzione input del modello, la funzione astratta compute di ogni unit`a della rete, partendo dai layer pi`u bassi, arrivando alle unit`a di uscita. Invocando la funzione compute l’unit`a aggiorna la sua uscita, contenuta nella sua variabile pubblica currentValue.
Gestione dei Pesi I pesi di un’unit`a della rete neurale sono contenuti all’interno della classe iNeuralUnit distinguendo da peso di output, hidden e il bias:
Listing 4.21: Strutture dei Pesi all’Interno di un’Unit`a
vector<weight*> inputWeights; vector<weight*> hiddenWeights; weight* bias;
Il tipo weight `e una struct definita in iNeuralUnit contenente il valore del peso, conte- nuto nella variabile pubblica value, e due variabili usate in modo esclusivo, a seconda del tipo di peso appartenente alla generica unit`a i:
• nel caso il peso ¯wij sia di input, viene usata la variabile input per conservare il
valore della features lij;
• nel caso il peso ˜wij sia di hidden, viene usata la variabile inHiddenReference che
contiene un riferimento all’unit`a j;
All’interno della struct weight sono conservate le informazioni riguardanti la derivata parziale rispetto a quel peso, in modo da agevolare le operazioni degli algoritmi di apprendimento che non dovranno usare strutture ausiliari (e parallele) per conservare i valori del gradiente.
4.1.3.2 Salvataggio e Caricamento
I modelli possono essere salvati in files xml e caricati in modo da essere usati successi- vamente per effettuare predizioni.
Il salvataggio viene effettuato invocando la funzione save del modello, la quale si occupa di salvare alcune informazioni generiche del modello, come il path del dataset su cui `e stato addestrato, o i contributi massimi e minimi (vedere Sez. 5.3). Si occupa,
inoltre, di salvare lo stato di ogni unit`a invocando la funzione save per ogni iNeuralUnit presente.
Il caricamento avviene invocando la funzione loadModel di un’istanza di ModelsFac- tory.
Un esempio completo di XML dei un modello NN4G `e presente in App. C.1.