Genetic Works

(REALLY!)

UN POTENTE ALGORITMO DI ELABORAZIONE DEI SEGNALI

REALIZZATO APPLICANDO ALLE RETI NEURALI GLI ALGORITMI GENETICI

Come è noto, l'attività nervosa encefalica si manifesta sulla cute attraverso variazioni del potenziale elettrico: tale attività è misurabile mediante degli elettrodi opportunamente posti. Il complesso di queste variazioni di potenziale costituisce un segnale che è detto elettroencefalogramma (EEG). Le difficoltà di rilevamento sono causate principalmente dell'impedenza della scatola cranica, che fa sì che il rapporto segnale/rumore scenda anche a -60 dB.


Figura 1 - Esempio di segnale EEG non trattato


Nostro compito era cercare di capire se sia possibile identificare l'istante preciso in cui il cervello di una persona manda ai muscoli un comando di movimento. A questo scopo disponevamo di una serie di rilevazioni fatte su di un soggetto che, in una stanza buia e silenziosa (per cercare di eliminare tutte le possibili interferenze) stava comodamente seduto in poltrona, ad occhi chiusi, e si limitava a muovere un dito.

Il segnale è stato rilevato mediante 26 elettrodi disposti secondo lo standard internazionale 10-20 nella versione aumentata, e la registrazione contemporanea dell'elettromiogramma del muscolo estensore delle dita ha permesso di avere una base dei tempi affidabile.

Come si può vedere dalla figura 1, il segnale è molto "difficile", nel senso che non vi è alcuna correlazione evidente tra esso e l'istante in cui è avvenuto il movimento.


Figura 2 - Schema di flusso della media sincrona


L'approccio tradizionale di analisi è la media sincrona, che si basa sul fatto che la media temporale degli EEG in periodi lunghi è praticamente nulla, quindi con molti segnali ripetuti e mediati in sincronia, il rumore dovrebbe cancellarsi. Tuttavia non è applicabile in tempo reale, ed inoltre non possiamo pensare ai fenomeni cerebrali come "ripetibili".

Si può capire come siano necessari sistemi d'analisi più intelligenti.

L'idea alla base delle Reti Neurali è quella di elaborare delle informazioni secondo un modello che prende spunto dal funzionamento del cervello umano: la rete è composta da un certo numero di nodi organizzati in strati (nel modello da noi adottato, il più utilizzato, ci sono due strati nascosti), ed ogni nodo è un neurone equivalente, modello funzionale di un insieme di neuroni. I nodi del primo strato fungono in realtà da recettori per il segnale, i nodi degli strati successivi lo elaborano sommando gli ingressi con un peso (sommazione spaziale, fatta in natura dalle sinapsi) e facendo passare il valore risultante per la funzione caratteristica del neurone (generalmente una sigmoide). Il valore di uscita dipende quindi da quello di ingresso in maniera profondamente non lineare.


Figura 3 - Rete Neurale in funzione


Il fatto che ogni connessione abbia un proprio peso consente alla rete di essere addestrabile e di mantenere memoria dell'addestramento ricevuto. Si parte da una certa topologia, e si cerca poi, a partire dai risultati ottenuti, di ottimizzare i valori dei pesi, che rappresentano la memoria distribuita delle Reti Neurali.

I metodi classici generalmente partono da una topologia fissa stabilita dall'operatore, che ovviamente, per cercare di ridurre la complessità della ricerca, fa delle ipotesi sul problema: questo implica una conoscenza (che non sempre è disponibile) del modello da adottare. Inoltre la connettività iniziale della rete è, nella maggior parte dei casi, totale, e solo durante l'addestramento può darsi che qualche connessione venga attenuata oppure eliminata. Si può tuttavia pensare di costruire un algoritmo che faccia evolvere tutta la topologia della Rete Neurale, e non solo l'insieme dei pesi.

Per eliminare la necessità di costruire a priori un modello del fenomeno, ed avere inoltre la possibilità di far evolvere tutta la topologia della Rete Neurale, abbiamo scelto di implementare l'addestramento delle Reti Neurali mediante un Algoritmo Genetico.

Esso consente ricerche in grande, evitando minimi locali, agendo non su di un solo elemento da modificare via via, ma su di una popolazione di elementi che viene fatta evolvere contemporaneamente. Questi elementi possono avere struttura qualsivoglia, purché si presentino all'Algoritmo Genetico con una codifica adeguata. Tale codifica viene detta genoma, in omaggio all'analogia biologica che si utilizza.

Nella forma da noi utilizzata l'Algoritmo Genetico si presenta come in figura 4.


Figura 4 - Schema di flusso dell'Algoritmo Genetico


Gli individui componenti la popolazione in questo caso sono ovviamente Reti Neurali. La popolazione viene inizializzata a caso. Ciascuna rete elabora il segnale ed in base all'uscita prodotta le viene attribuita una cifra di merito (fitness) che indichi la sua attitudine a svolgere il compito assegnato. Nel nostro caso la fitness è tanto maggiore quanto più l'uscita prodotta è uguale all'uscita attesa (la somiglianza fra le funzioni è calcolata utilizzando il prodotto di scarto quadratico medio, norma di Hilbert e norma di Lagrange). Proporzionalmente alla loro "bontà" alcune reti sopravvivono ed hanno la possibilità di riprodursi.

La riproduzione, nella nostra implementazione, che si discosta da quella classica, comprende anche il crossover, ed avviene nel modo seguente: con probabilità pari alla propria fitness vengono scelti due individui come genitori; scelto un sito di taglio per genitore, avviene il crossover che, prendendo una parte da un genitore ed una dall'altro, origina i due figli. Dopo la riproduzione avviene una mutazione di un numero casuale di bit in posizioni casuali in ciascun genoma. Si ripete questo procedimento fino a completare la popolazione.

L'ottimizzazione di NN tramite GA è stata già tentata con successo, ma i risultati noti nella bibliografia sono soprattutto relativi a situazioni in cui i segnali sono di tipo binario, mentre il segnale oggetto del nostro studio è di tipo analogico.

La prima versione del programma

L'algoritmo esiste in una prima implementazione, volutamente poco sofisticata, nella quale abbiamo utilizzato come metafora una popolazione di esseri unicellulari, quali ad esempio dei batteri. Il singolo individuo non ha capacità di apprendere, in quanto tutto il suo comportamento è già "scritto" nei suoi geni. Pertanto, l'unica via di miglioramento è il susseguirsi delle generazioni: in questo modo è la popolazione nel suo complesso ad apprendere. Secondariamente, lo schema dei geni è molto rigido, ammettendo solo genomi di lunghezza fissa. Ogni individuo genera un numero di discendenti tanto più grande quanto maggiore è la sua capacità di sopravvivere (ovvero quanto migliore è la sua elaborazione del segnale); successivamente si applicano i due operatori genetici classici. Il crossover avviene mediante la combinazione di due genomi, che vengono tagliati in un medesimo punto e ricomposti scambiando le due "code"; la mutazione modifica casualmente alcuni bit del genoma.


Figura 5 - Crossover


Poiché era necessario scegliere una funzione di uscita attesa, se ne è scelta una che fosse positiva nella zona di movimento e negativa altrove, in modo che la rete neurale segnalasse anche visivamente l'istante del movimento.

L'elaborazione del segnale è stata effettuata in tre stadi.

1. Taratura dell'algoritmo. L'algoritmo dipende da numerosi parametri, che sono stati variati uno alla volta per identificare quale fosse per ciascuno di essi il valore più adeguato al tipo di segnale.

2. Addestramento. È stato effettuato su di un insieme di segnali (training set) composto da un numero di campioni limitato, per non penalizzare eccessivamente le prestazioni dell'algoritmo, e tuttavia selezionato al fine di presentare alle reti neurali una gamma il più possibile completa di esempi da cui apprendere. Durante l'addestramento la popolazione evolve fino a quando si trovi in essa una rete soddisfacente.

3. Controllo o riconoscimento. La rete neurale "ottima" così generata viene utilizzata per elaborare le informazioni provenienti da prove differenti da quelle utilizzate nell'addestramento, permettendo una valutazione in media della bontà della rete.

In definitiva, i risultati ottenuti con questa implementazione sono stati appena soddisfacenti (con una sola punta del 56% di riconoscimenti corretti dell'istante di movimento), ma hanno permesso di mostrare come l'algoritmo utilizzato sia in grado di generalizzare l'analisi del segnale, ottenendo delle reti neurali che si comportano in maniera adeguata.

Prescindendo, tuttavia, dai risultati effettivi, ad un'analisi qualitativa delle reti ottenute in questo modo si nota ad esempio che la loro topologia è fortemente ridondante: vi è spesso la presenza di nodi non connessi all'uscita, o altrimenti inutilizzati, dei quali l'algoritmo non riesce a sbarazzarsi. Resta poi il dubbio se la topologia fissata all'inizio sia effettivamente, come si diceva, quella più opportuna per il problema che si affronta. Non dimentichiamo che è nostro obbiettivo sviluppare un algoritmo che sappia trattare segnali di qualunque tipo: ottimizzarlo per trattare segnali EEG sarebbe una inaccettabile perdita di generalità.

La versione GW5

Dalle considerazioni appena esposte nasce una seconda versione del programma: GW5.

Aumenta la complessità degli individui, che acquistano la capacità di apprendere prima di riprodursi; la struttura dei figli non è necessariamente uguale a quella dei genitori, anche se sarà simile e comunque capace di svolgere le medesime funzioni. Per tornare all'analogia biologica possiamo pensare adesso ad una popolazione di piccoli mammiferi.


Figura 6 - La codifica binaria e la codifica "a puntatori"


Per implementare la capacità di apprendimento degli individui, separata dall'apprendimento della popolazione nel suo complesso, si è deciso di inserire un ulteriore passaggio di ottimizzazione, stavolta utilizzando un "classico" algoritmo di back-propagation sulle connessioni di ogni Rete Neurale. Questo passaggio viene effettuato prima della fase di riproduzione, dando così alle Reti stesse la possibilità di "apprendere" e di trasmettere ai propri discendenti tale conoscenza.

Come avviene tale trasmissione? Si è deciso, per semplicità, di "integrare" direttamente nel genoma di ogni individuo i cambiamenti avvenuti. Ciò non sarebbe rigorosamente corretto, in quanto l'apprendimento e l'adattamento all'ambiente possono modificare la struttura esterna di un organismo biologico, ma in ogni caso non ne modificano il genoma. La nostra scelta non inficia però la validità del modello, in quanto consideriamo il figlio che otteniamo come se fosse al termine dell'insegnamento da parte dei genitori, anziché un prodotto "nuovo". Ci dà inoltre un notevole vantaggio dal punto di vista implementativo, in quanto ci consente di mantenere immutato l'Algoritmo Genetico.

È stato necessario soltanto inserire una differente codifica della rete: a quella binaria su cui si applicano gli operatori genetici abbiamo aggiunto una struttura "a puntatori" per semplificare l'algoritmo di elaborazione del segnale e l'ottimizzazione via back-propagation.

Per lo stesso motivo si sono utilizzate per la funzione di uscita attesa forme più "brusche".


Figura 6 - Esempio di schermate di GW5 con reti di struttura differente


GW5 è un algoritmo più generale, che permette di gestire contemporaneamente Reti con struttura diversa (per numero di strati, di nodi per strato, numero di connessioni, eccetera) e di avere i siti di taglio nell'operazione di crossover in posizione diversa nei due genitori. Questa maggiore generalità ha una importante conseguenza, cioè che la struttura dei figli sarà quasi sempre diversa da quella dei genitori, e quindi le Reti Neurali componenti la popolazione avranno in genere topologie anche molto diverse fra loro.


Figura 7 - Esempio di esclusione di C2


GW5 si è dimostrato più flessibile, poiché elimina autonomamente i nodi inutili in quanto non connessi o con valori al di sotto di una certa soglia, ed è in grado di escludere ingressi che si rivelino non funzionali all'uscita da generare.

GW5 si è dimostrato più efficiente, poiché ha generato soluzioni più snelle di quelle della versione precedente e che tuttavia ottengono risultati migliori. Ha inoltre esplorato uno spazio di configurazioni molto più ampio di quello generalmente considerato in letteratura, proponendo più volte delle Reti ottime retroazionate, concetto che non è mai stato contemplato nella teoria classica delle Reti Neurali.

GW5 si è dimostrato più efficace, poiché ha generato Reti ottime in grado di ottenere performance migliori della versione precedente, ottenendo costantemente una percentuale di riconoscimenti corretti superiore al 60%. Inoltre si sono ottenute, in alcuni casi, Reti Neurali sensibili ai fronti di discesa, risultato che si allinea ad un fatto ben noto dalla letteratura: il potenziale evento-correlato ripulito dal rumore si presenta come un fronte di discesa nel segnale.

GW5 si è dimostrato più lento della versione precedente, come si può ben comprendere dalla mole di informazioni in più che deve elaborare.

Conclusioni

La valutazione finale mostra come l'algoritmo sia efficace anche per segnali complessi e molto generale, tanto che senza alcuna modifica potrebbe essere già utilizzato per altre applicazioni come il riconoscimento di segnale vocale o di caratteri (con opportuna codifica).

L'elaborazione del segnale è soddisfacente, anche se non del tutto. È comunque un sistema che permette, dopo l'addestramento, di studiare il segnale EEG in tempo reale: si può pensare, infatti, di farlo passare direttamente dagli elettrodi alla Rete ottima, la quale fornisce la risposta con un ritardo dovuto solo ai tempi di elaborazione.

Gli sviluppi possibili sono molteplici: ad esempio un raffinamento ulteriore degli algoritmi o del calcolo della fitness, un'implementazione massicciamente parallela, una recezione in ingresso dei segnali provenienti da tutti i canali disponibili, in modo che sia l'algoritmo ad eliminare quelli non necessari.

Ricapitolando, ci sembra quindi di poter affermare che l'algoritmo da noi implementato ed utilizzato in GW4 ed in GW5 sia discretamente valido. Infatti esso è generale: il campo di applicabilità è molto vasto; è potente: l'applicazione ad un segnale "difficile" a valori reali ha portato a risultati che possiamo definire soddisfacenti; è efficiente: fra i risultati ottenuti si sono presentati casi non prevedibili a priori (come quello della rete retroazionata); è espandibile: gli sviluppi potenziali non sono del tutto trascurabili.