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.
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à.
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.
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.
La prima versione del programma
La versione GW5
Conclusioni