\articolo{Visual Neurocomputing: Una shell per creare, addestrare e usare reti neurali}{Gabriele Falcioni e Stefano Guarnieri}

\paragrafo{Introduzione}
\noindent La nascita delle reti neurali artificiali (RNA) si può ricondurre alla
necessità di automatizzare attività che l'uomo compie inconsciamente e che,
quindi, non possiedono una descrizione algoritmica.

Una RNA, similmente alla omologa rete biologica, è un calcolatore parallelo
ad architettura distribuita, composto da elementi di elaborazione (neuroni)
collegati tra loro tramite canali unidirezionali, detti connessioni (per una più
ampia spiegazione si consulti [1]). Un'interessante caratteristica degli
elementi di elaborazione è la loro località: i calcoli eseguiti da un
neurone dipendono esclusivamente dai valori istantanei assunti dalle
connessioni d'ingresso e dallo stato della sua memoria interna. Questa
caratteristica implica la possibilità di costruire reti arbitrariamente
grandi in modo relativamente semplice.

Una RNA, pur basandosi su paradigmi biologici, è per forza di cose un
modello estrememente semplificato. Ogni neurone è composto da \textit{n} connessioni
d'ingresso, dette sinapsi, che ``pesano'' gli ingressi; questi valori vengono
quindi sommati, realizzando in pratica una combinazione lineare degli
ingressi. L'uscita del combinatore coincide con l'ingresso di un blocco non
lineare, che esplica le mansioni di funzione di decisione (funzione di
attivazione).

È possibile scegliere tra ampie classi di funzioni di attivazione, non elencate
in questa sede: l'importante è che queste presentino una saturazione ai loro estremi
(abbiano cioè una forma ``schiacciata''). Un esempio di neurone è riportato in
figura~\ref{fig:neurone}.

\begin{figure}[ht]
\def\epsfsize#1#2{0.4#1}
\begin{center}\leavevmode\epsffile[0 0 513 265]{neuro/neurone.ps}\end{center}
\caption{\label{fig:neurone}\small Schema di un neurone generico}
\end{figure}

A livello di rete, la stragrande maggioranza delle applicazioni fa uso di
una struttura detta Multilayer Feedforward Perceptron (MLP): i singoli
neuroni vengono organizzati in strati (o layer), in modo che ogni neurone
appartenente a un certo strato si connetta a tutti i neuroni dello strato
precedente (vedi figura~\ref{fig:mlp}).

Esistono altre topologie di rete, usate prevalentemente per la ricerca
avanzata o per applicazioni particolari, che preferiamo omettere per
maggiore chiarezza.

\begin{figure}[ht]
\def\epsfsize#1#2{0.5#1}
\begin{center}\leavevmode\epsffile[0 0 457 238]{neuro/mlp.ps}\end{center}
\caption{\label{fig:mlp}\small Schema di una generica rete MLP}
\end{figure}

\paragrafo{Teoria di funzionamento}
\noindent La pesatura degli ingressi è realizzata tramite moltiplicatori,
in cui uno dei fattori è l'ingresso e l'altro un parametro libero. Questo
significa che, al variare di tutti i parametri liberi, una stessa RNA darà,
fissati gli ingressi, risultati diversi.

Esistono teoremi (Cybenko; Hornik, Stinchcombe, White) che dimostrano la
possibilità, per una rete MLP, di approssimare una qualsiasi funzione
continua in un intervallo chiuso multidimensionale. Questo significa che una
rete MLP è potenzialmente in grado si calcolare qualunque cosa. Per ottenere
questo risultato occorre agire sui parametri liberi della rete MLP (le
sinapsi, ma in qualche caso anche la funzione di attivazione): qui entra in
gioco il concetto di apprendimento.

A questo punto occorre premettere che una descrizione formale degli algoritmi
di apprendimento richiederebbe una notevole quantità di formule
matematiche che vogliamo evitare. Per questo motivo, la descrizione degli
algoritmi si manterrà sul piano qualitativo. Per le anime più curiose, un
articolo molto rigoroso, eppure relativamente semplice (per gli addetti ai
lavori \c{:-)}) sulla storia degli algoritmi di apprendimento si trova in [2].

Il tipo di apprendimento che prenderemo in considerazione è detto
supervisionato, in quanto viene svolto fornendo alla rete la coppia ingresso/uscita
desiderata. Ovviamente, è necessario conoscere il risultato esatto
della funzione da calcolare; nel caso non fosse possibile, si ricorre ad
algoritmi di apprendimento di tipo non supervisionato.

L'idea di base dell'algoritmo è di confrontare il risultato della rete con la
funzione da far apprendere, su un elevato numero di punti del dominio.
Quello che si ottiene è una funzione che rappresenta l'errore
dell'approssimazione. L'apprendimento consiste nel minimizzare questo errore.

La funzione errore da minimizzare è l'errore quadratico medio (Mean Square
Error, MSE) su tutti i punti del dominio; per cercarne il minimo (sperando
che sia assoluto) si utilizza un semplice algoritmo che converga al punto in
cui il gradiente si annulla. Poiché il gradiente dipende da tutti i
parametri liberi della rete, il calcolo può diventare estremamente oneroso;
si preferisce, quindi, calcolarne una approssimazione detta ``Generalized
Delta Rule'' o, più semplicemente, ``Backpropagation'' [2].

\begin{itemize}
\item{Si costruisce un insieme di coppie ingresso-uscita della funzione da far
apprendere alla rete. Poiché, in generale, la funzione può avere dominio e
codominio in insiemi multidimensionali, ogni elemento della coppia sarà un
vettore. Chiameremo l'ingresso input pattern e l'uscita output desiderato. }
\item{Si sceglie arbitrariamente una coppia ingresso-uscita e si sottopone l'input
pattern alla rete MLP.}
\item{La rete MLP esegue i calcoli dal primo all'ultimo
strato, le cui uscite rappresentano l'output della rete (fase forward).}
\item{Si calcola il vettore degli errori, dato dall'output desiderato meno
l'output della rete.}
\item{Si calcola l'approssimazione del gradiente per ogni
neurone della rete e si effettua la modifica dei parametri liberi
corrispondenti. Si procede a partire dall'ultimo layer fino al primo (fase
backward).}
\item{Il procedimento si ripete per ogni coppia ingresso-uscita a
disposizione. Quando queste sono terminate e non sono in numero sufficiente
a caratterizzare la funzione da approssimare, si utilizzano di nuovo le
stesse coppie; ognuna di tali serie di apprendimento viene detta epoca.
L'apprendimento ha termine quando l'MSE è inferiore a una soglia prefissata
o, a scelta, dopo un certo numero di epoche di apprendimento.}
\end{itemize}

\noindent Come accennato in precedenza, non solo le sinapsi possono essere modificate,
ma anche alcuni tipi di funzioni di attivazione: tra queste, una è stata
sviluppata da uno degli autori nella sua tesi di laurea e pubblicata in [3].
La funzione SG (Sigmoide Generalizzata, figura~\ref{fig:sg}) è una curva spline (cubica
Catmull-Rom) i cui punti di controllo sono parametri liberi. Per semplicità,
i punti di controllo hanno ascissa fissata: solo l'ordinata è libera da
vincoli.

\begin{figure}[ht]
\def\epsfsize#1#2{0.5#1}
\begin{center}\leavevmode\epsffile[0 0 380 182]{neuro/sgfunction.ps}\end{center}
\caption{\label{fig:sg}\small Funzione di attivazione SG}
\end{figure}

\paragrafo{Proprietà delle reti MLP}
\noindent Abbiamo già visto che le reti MLP si addestrano tramite l'uso di
esempi. Questo significa che una RNA è utilizzabile anche in quei casi in cui non è
nota la forma analitica della funzione (o del processo) da apprendere.

Un'altra interessante proprietà è quella della generalizzazione. La
struttura delle reti MLP è tale da consentirne l'uso anche per approssimare
la funzione in punti non presenti nell'originario insieme di addestramento.
Questo significa che la RNA è in grado di apprendere il legame funzionale
che esiste tra ingresso e uscita e di riprodurlo su qualsiasi ingresso.

Ovviamente, il grado di generalizzazione acquisito dipende strettamente
dalla qualità e quantità degli esempi usati nell'addestramento, nonché dalla
geometria della rete. Spesso, per ottenere risultati accettabili è
necessaria una lunga e faticosa serie di prove.

\paragrafo{Applicazioni delle RNA}
\noindent (E ora, un po' di fantascienza \c{:\^})

\noindent Immaginiamo il classico programma di image-processing che disponga di un
bellissimo effetto; noi vorremmo incorporare tale effetto in un nostro
programma. Per iniziare, ci procuriamo una serie di coppie di immagini,
prima e dopo la ``cura'' dell'effetto in questione; diamo in pasto alla
nostra RNA le coppie di immagini, la prima come ingresso e la seconda come
uscita desiderata. La RNA, effettuato l'apprendimento (con esito positivo),
rappresenta una ottima approssimazione dell'effetto. Ora possiamo, tramite
un semplice passo forward, trasformare una qualsiasi immagine in ingresso
nell'immagine che si sarebbe ottenuta (o quasi) con il programma di
partenza\ldots

Più realisticamente, ci sarebbero da risolvere un certo numero di problemi
riguardanti la scelta delle immagini di esempio, quante utilizzarne, se fare
o meno del preprocessing per ottenere dati più facilmente trattabili dalla
rete, solo per scoprire\,---\,alla fine\,---\,che è più veloce l'approccio
procedurale\ldots

In generale, le RNA rappresentano una tecnica generale di calcolo e, in
quanto tale, suscettibile di valutazione caso per caso. Quello che segue è
un breve (e incompleto) elenco delle possibili applicazioni delle RNA:

\begin{itemize}
\item{problemi di controllo automatico;}
\item{problemi di classificazione e, come caso particolare:}
\begin{itemize}
\item{riconoscimento vocale e di immagini (OCR);}
\item{identificazione (predizione) di sistemi non lineari incogniti;}
\end{itemize}
\item{filtraggio non lineare e, come caso particolare:}
\begin{itemize}
\item{compressione e decompressione dati.}
\end{itemize}
\end{itemize}

\paragrafo{Visual Neurocomputing}
\noindent Il software che presentiamo è composto da due elementi principali: un editor
grafico di reti neurali e un simulatore. Il primo è legato, per concezione
e implementazione, al sistema operativo di \A; il secondo è stato
progettato per essere portabile.

L'interazione tra i due avviene tramite un'apposita API pubblica, fortemente
orientata all'oggetto, che isola completamente i due ambienti. Tale
approccio permette al simulatore di funzionare efficacemente anche in
ambienti capaci di calcolo distribuito.

Il programma è attualmente un work in progress. La versione distribuita ha
alcune limitazioni per questo motivo. Contiamo di rimuoverle nelle prossime
versioni.

L'editor permette di lavorare su una singola RNA alla volta, su questa è
possibile intervenire tramite una grande quantità di parametri progettuali:
\begin{itemize}
\item{numero di ingressi e uscite;}
\item{numero di ritardi in ingresso (utile per applicazioni di DSP);}
\item{numero di strati (o layer);}
\item{numero e tipo di neuroni per ogni strato (il tipo può essere uguale per tutti i neuroni
o scelto per ogni singolo neurone);}
\item{uso di un offset per velocizzare l'apprendimento
(nella figura~1 l'offset è rappresentato da {$\text{\textit{w}}_{\text{0}}$});}
\item{vasta scelta di funzioni di attivazione;}
\item{possibilità di adattare selettivamente sia sinapsi che
funzioni di attivazione (anche in questo caso sia a livello
di singolo neurone che per ogni strato completo).}
\end{itemize}

\noindent Tramite l'uso di meccanismi di selezione multipla è possibile:
\begin{itemize}
\item{salvare parte di una rete (questa funzionalità è
indispensabile quando si progettano compressori dati);}
\item{forzare uniformi cambiamenti di attributi;}
\item{rimuovere neuroni;}
\item{inserire neuroni in vari punti della rete.}
\end{itemize}

\noindent Quasi tutte le operazioni avvengono tramite menu, anche se non escludiamo
che, nelle prossime versioni, si faccia un uso più esteso di bottoni, in
modo da rendere l'interfaccia ancora più amichevole all'utente.

Il simulatore si preoccupa del calcolo effettivo della rete e del suo
addestramento. I dati su cui la rete agisce provengono da file esterni.
Tramite apposite opzioni si possono specificare le sorgenti di input e di
output della rete. Il simulatore può funzionare in due modi:

\begin{itemize}
\item{Run Forward\,---\,calcolo;}
\item{Learn\,---\,calcolo e adattamento.}
\end{itemize}

\noindent Nel primo caso la rete deve essere già addestrata ed è usata per produrre
dei risultati. Il simulatore legge un file con gli input per la rete e ne
produce uno con gli output della rete.

Nel secondo caso la rete viene adattata seguendo la procedura descritta
precedentemente ed è necessario fornire al simulatore una seconda sorgente
di dati, contenente gli output desiderati per la rete. In questo caso si può
fare a meno di generare un file di output in quanto, spesso, non contiene
informazioni utili.

Durante la fase di Learn è possibile visualizzare, contemporaneamente al
procedere della simulazione, lo stato delle sinapsi o della funzione di
attivazione di un numero qualsiasi di neuroni. Oltre a questo è possibile
seguire graficamente l'andamento dell'MSE.
In ogni momento è possibile fermare la simulazione e alterare qualunque
parametro che non comporti variazioni alla geometria della rete.

I file elaborati dal simulatore sono molto semplici: si tratta di
successioni di numeri floating point in singola precisione in standard IEEE
754, lo stesso tipo di dati elaborato dal coprocessore matematico 68881.
Questo dovrebbe permettere a chiunque di leggere e scrivere file di dati per
le proprie reti.

Per il funzionamento il programma richiede una
macchina con accoppiata 68020+68881 o superiore e AmigaOS V37 o
successivo. La quantità di memoria non è critica in quanto il programma può
funzionare con buffer di I/O grandi a piacere. Se trovate bug nel programma
ringraziate (nell'ordine) gli autori e il SAS/C 6.55 \c{:)}.

\paragrafo{Un esempio di apprendimento}
\noindent Come esempio di utilizzo, caso ampiamente visto in letteratura, vediamo la
predizione di una serie numerica caotica: la serie di Mackey-Glass [4].
Questa serie rappresenta un modello per la produzione di globuli bianchi in
pazienti leucemici, ed è una equazione differenziale non lineare che genera
un caos di tipo deterministico: ciò è importante, perché il caos non
deterministico non è prevedibile! (quindi non pensate di poter prevedere il
vostro prossimo terno al lotto\ldots)

Si prendono come pattern d'ingresso i primi sei elementi della serie
numerica, mentre come uscita desiderata si considera il settimo: si effettua
un passo di apprendimento, poi si scala tutto di un elemento (il nuovo
pattern d'ingresso sarà dato dagli elementi dal secondo al settimo, mentre
l'uscita desiderata sarà l'ottavo elemento) e si ripete il procedimento.
Quando l'MSE sarà sufficientemente piccolo, la rete in questione avrà
appreso a prevedere, dati sei valori contigui della serie, il valore
successivo.

\paragrafo{Conclusioni}
\noindent A questo punto ci si può chiedere a chi è rivolto questo software:
sicuramente, gli studenti universitari di ingegneria elettronica ne saranno
i primi beneficiari; ciononostante, noi crediamo che molti altri utenti
\A
possano trarre vantaggio da architetture neurali.

Questo programma, al di là delle sue valenze didattiche, può essere utile per
provare se il calcolo neurale è adatto a risolvere i propri problemi senza dover
scrivere migliaia di linee di codice. Questo è l'invito che rivolgiamo
in particolar modo a coloro che operano nei campi dell'audio e dell'image processing.

\begin{thebibliography}{10}

\bibitem{ref1} S. Haykin. \emph{Neural Networks: A Comprehensive
Approach}. IEEE Press, 1994.
\bibitem{ref2} B. Widrow, M.A. Lehr. \emph{30 Years of Adaptive Neural Networks: Perceptron, Adaline and
Backpropagation}.  Proceedings of the IEEE, Vol.~78, No.~9, settembre 1990.
\bibitem{ref3} S. Guarnieri, F. Piazza, A. Uncini.
\emph{{\selectlanguage{english}Multilayer Neural Networks with Adaptive Spline-based Activation
functions}}.  Proceedings of the WCNN'95, Washington DC, USA, 1995.
\bibitem{ref4} W.C. Mead, R.D. Jones, Y.C. Lee, C.W. Barnes, G.W. Glake, L.A. Lee,
M.K. O'Rourke. \emph{Prediction of chaotic time series using CNLS-NET\,---\,example: The Mackey-Glass
equation}. Technical Report LA-UR-91-720, Los Alamos National Laboratory, Los Alamos (NM), USA,
1991.
\end{thebibliography}

\autore{Gabriele Falcioni\\
Via E. Cialdini 50\\
I-60122 Ancona AN}
{Internet: falcioni@fastnet.it}

\autore{Stefano Guarnieri\\
Via Esino 151/a\\
I-60020 Torrette AN}
{Internet: bingo@eealab.unian.it}

\citazione{\selectlanguage{english}%
\emph{Once}, adv.: Enough.}{Ambrose Bierce, \emph{The Devil's Dictionary}}
