.

Rivista #230: Arduino e le reti neurali


Arduino_neurali-640x457 Rivista #230: Arduino e le reti neurali

Tra i contenuti del fascicolo 230 (Novembre 2018), attualmente in edicola, dopo una panoramica sulle reti neurali, ne valutiamo l’implementazione attraverso la piattaforma Arduino.

Dopo aver introdotto il concetto di Intelligenza Artificiale nell’articolo sui sensori pubblicato nel fascicolo precedente, vediamo come applicare le tecniche di AI all’hardware Arduino, Raspberry Pi ed anche ai tradizionali microcontrollori.

La necessità di queste tecniche nasce dalla considerazione che la programmazione classica diventa impraticabile quando si ha a che fare con molti input sensoriali di tipo analogico (ovvero che forniscono valori continui) e con attuatori non di tipo ON/OFF come motori e servocomandi; in questi casi è conveniente orientarsi verso Reti Neurali.

In queste pagine cerchiamo di chiarire cosa sono e come possono essere utilizzate in un hardware minimale come Arduino. Le utilizzeremo a cominciare da un semplice sistema di “obstacle avoidance” ossia di movimento evitando ostacoli e rimanendo in perimetri definiti. Per questo esempio utilizzeremo la piattaforma robotica “Ardusumo” ma nulla vieta di impiegare altri robot semoventi come “Alphabot”.

RETI NEURALI

Le Reti Neurali traggono origine dalla definizione del Percettrone, che Frank Rosenblatt creò nel 1958 ispirandosi al funzionamento dei neuroni. La loro applicabilità risale però all’introduzione delle funzioni di trasferimento non lineari e dell’algoritmo di correzione degli errori “Error Back Propagation” (Rumelhart and McClelland, 1986) riconducibili agli anni “ottanta” del secolo scorso.

Delle Artificial Neural Network (ANN) o più brevemente NN, è poi nata una branca chiamata “connessionismo”. Il nome è abbastanza autoesplicativo, in quanto la tecnica delle NN prevede una  computazione distribuita su diversi nodi interconnessi.

Una Rete Neurale è composta, in genere, da almeno tre strati di nodi connessi in catena: il primo è sostanzialmente un semplice buffer di input, mentre il terzo realizza un buffer di output. In realtà, poiché lo strato di input non ha una funzione che non sia quella di propagare l’input verso il primo vero strato elaboratore, molto spesso le reti di questo tipo vengono chiamate reti a due soli strati. Venendo al nostro esempio con “Ardusumo”, il primo strato raccoglie gli input sensoriali e l’ultimo l’azionamento dei motori (Fig. 1).

Fig.1-420x273 Rivista #230: Arduino e le reti neurali

In mezzo c’è un importantissimo strato, in genere chiamato strato nascosto (hidden) perché non è in rapporto diretto con l’esterno. Naturalmente esistono versioni di NN molto più complesse (Fig. 2), con più strati intermedi, con collegamenti inter-strato (convolution NN) o con buffer di memoria temporanea per la simulazione di sistemi dinamici, in cui lo stato precedente ha la sua importanza (recurrent NN); per il momento ci riferiremo alla versione base delle NN, che può già rappresentare un ottimo approssimatore universale di funzioni (in->out).

Fig2-3-640x183 Rivista #230: Arduino e le reti neurali

L’elemento fondamentale della rete neurale è il nodo. Questo raccoglie l’output dei nodi dello strato precedente ognuno moltiplicato per il peso del link corrispondente. Nella struttura classica tutti questi valori vengono sommati a formare un valore, chiamato attivazione del nodo, che viene passato ad una funzione di trasferimento che fornisce l’output effettivo del nodo. Questo output sarà propagato ai nodi dello strato successivo. Lo scopo della funzione di trasferimento (chiamata anche funzione di attivazione) è cruciale. Infatti proprio l’adozione di funzioni non lineari ha permesso alle reti neurali di diventare degli approssimatori universali, in quanto, insieme al metodo intelligente di correzione degli errori, permettono di trasformare lo spazio dei valori di input in uno spazio fittizio che può risolvere qualunque associazione input->output, a patto di avere un numero adeguato di nodi intermedi.

Per permettere questa proiezione da uno spazio vettoriale ad un altro, la funzione di attivazione è in genere di tipo “squashing”, cioè comprime l’output entro valori massimi e minimi, in modo da costringere i pesi delle connessioni ad evolvere in modo complesso. Le funzioni di attivazione che sono state proposte sono molte, ma le più utilizzate sono quella sigmoide (detta anche logistica) (1/(1+exp(-x)), la tangente iperbolica e quella rettificatrice (ReLU), insieme ovviamente a quella lineare unitaria utile in certe situazioni (Fig. 3).

Le reti neurali sono un sistema Feed Forward (in avanti dall’input all’output) ad apprendimento supervisionato, ovvero vengono inizialmente costruite con pesi casuali nelle connessioni e poi addestrate tramite un numero consistente di coppie di valori input->output. In questo modo finiscono per approssimare, interpolare ed estrapolare una funzione che lega un input multidimensionale ad un output multidimensionale anche in modo complesso; in sostanza, compiono una sorta di regressione statistica multivariata. Il meccanismo è noto con il nome di Error Back Propagation (EBP); in pratica, a partire dall’output prodotto spontaneamente dalla rete in seguito ad certi valori di input, si determina l’errore quadratico  commesso da ogni nodo di output e si determina la sua derivata in funzione dei singoli pesi afferenti al nodo. A questo punto si correggono i pesi applicando ad essi una variazione proporzionale all’opposto della derivata così calcolata. L’efficacia del metodo sta nel fatto che l’errore quadratico si può riportare indietro allo strato precedente applicando la regola della catena delle derivate; in questo modo si aggiornano i pesi di tutte le connessioni ottimizzando l’errore quadratico medio della rete complessiva. Non è garantito il raggiungimento dell’ottimo assoluto, ma sicuramente l’errore scende fino a quando può fermarsi a un valore minimo. Se il numero dei nodi di input è stabilito dal numero delle grandezze di ingresso e quello dei nodi di output è definito dalle grandezze di  uscita, i nodi dello strato intermedio sono da decidere, in fase progettuale, un po’ per esperienza, un po’ in funzione della complessità della funzione da approssimare ed un po’ per tentativi. Troppo pochi possono non far scendere l’errore in modo soddisfacente, mentre troppi possono portare la rete a non sintetizzare in modo efficiente il legame input->output che si vuole approssimare. Una volta addestrata la rete può essere utilizzata, per eseguire la funzionalità che ha imparato, fornendo un input e rilevando l’output. C’è da notare che non si tratta di ripetere gli esempi, ma di poter contare sulla generalizzazione di una funzione multidimensionale anche complessa, appresa a partire da un numero limitato di esempi prototipali.

Tabella-1-640x345 Rivista #230: Arduino e le reti neurali

….

Il progetto prosegue con:

LIBRERIA NNET PER ARDUINO

ESEMPIO CON LA FUNZIONE XOR

RETE NEURALE PER PILOTARE ARDUSUMO

DIMENSIONI DI RETI POSSIBILI SU ARDUINO UNO

CONCLUSIONI

In questo articolo vi abbiamo spiegato come sia possibile utilizzare la tecnologia delle reti neurali anche con Arduino. Al prezzo di un certo lavoro nel definire la rete e gli esempi da sottoporre per l’addestramento e, soprattutto, a fronte di qualche difficoltà nel definire il completamento dell’addestramento, si possono utilizzare semplici e rapidissime strutture che, una volta addestrate, ricreano complesse funzioni multidimensionali continue.

L’articolo completo è pubblicato sul numero 230, Novembre 2018, acquistabile in tutte le edicole. 

 

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.