Qualche tempo fa abbiamo parlato di machine learning, presentando nel dettaglio la binary classification e accennando all’esistenza di molti altri modelli in grado di prevedere le azioni da intraprendere in funzione dei dati che sono già in nostro possesso. Oggi analizzeremo il modello in assoluto più conosciuto, non solo tra gli addetti ai lavori ma anche tra le persone che di matematica e informatica conoscono ben poco: le reti neurali, o Artificial Neural Network. Il nome spiega di per sé perché siano così note al grande pubblico: una rete di computer, semplici macchine senza intelligenza e senza personalità, in grado di simulare il funzionamento dell’organo più complesso del corpo umano, il cervello. Mettiamo le mani avanti dicendo che le ANN non sono nemmeno lontanamente paragonabili a un vero cervello: sono molto meno complesse, molto meno potenti e molto meno versatili. E ad essere onesti, il loro funzionamento è solo vagamente simile a quello del cervello. Insomma, di neurale hanno ben poco: le ANN prendono il proprio nome dalla somiglianza alla struttura reticolare del cervello. Le ANN infatti sono grafi composti da unità di base, i neuroni, connesse tra di loro per formare una complessa rete in grado di trasformare un input in un preciso output. Bene, la somiglianza con il cervello finisce qui. Ora concentriamoci sulla struttura di un neurone e poi penseremo a come connetterne molti tra loro per ottenere qualcosa di utile.

Struttura dei neuroni

Un neurone ha una struttura molto semplice e può essere rappresentato come la combinazione di un sommatore Σ e di una funzione di soglia σ. Il sommatore prende in ingresso tutti gli input provenienti dall’esterno e ne calcola la somma, che viene passata come input alla funzione di soglia. Questa solitamente è una funzione particolare, una sigmoide, chiamata così per la sua caratteristica forma a S: la sua peculiarità è che restituisce sempre un valore compreso tra 0 e 1, che andrà a costituire l’output del neurone.

Neurone e sigmoide – Credits: Microsoft TechNet

L’immagine qui sotto spiegherà meglio il concetto: i valori xi a sinistra, connessi al neurone a destra, costituiscono l’input. Per ogni connessione è presente inoltre un valore vi, chiamato peso, che viene moltiplicato per il valore in ingresso a cui è associato: questo permette di dare un peso diverso a ogni componente dell’input, poichè un ingresso con un peso elevato avrà un effetto maggiore sulla somma calcolata all’interno del neurone. Il neurone deve quindi sommare tutti i valori xi·vi e passare il risultato alla sigmoide, che produrrà l’output di questa semplice rete neurale: dato che uno solo dei due livelli contiene un neurone, questa rete ha profondità 1.

Semplice rete neurale di profondità 1.

Struttura della rete

E se volessimo estendere la rete con molti altri neuroni in modo da formare più livelli consecutivi? Semplice, basta collegare tutti i neuroni di un livello a tutti i neuroni del livello successivo, fino a raggiungere quello finale, come si può notare in questa immagine: ci sono T livelli al cui interno sono presenti dei neuroni, quindi questa rete ha profondità T. Inoltre, se escludiamo l’ultimo livello visibile, notiamo che ci sono T-1 livelli nascosti, quindi ogni ANN di profondità T ha T-1 livelli nascosti, o hidden layers. Per la maggior parte dei problemi “semplici” sono sufficienti un paio di livelli nascosti e un numero di neuroni paragonabile alla dimensione dell’input, cioè a quanti valori vengono passati in ingresso alla rete.

Rete neurale di profondità T con T-1 hidden layers.

Utilità

Quanto può essere utile un modello come questo? La risposta è più complessa di quanto possa sembrare, ma proviamo a darne una soddisfacente. Nell’articolo di introduzione al machine learning abbiamo descritto la binary classification, dicendo che è il modello più semplice che possiamo implementare. Si riesce a simulare quel modello con una ANN? La risposta è sì e per renderlo possibile è sufficiente avere un solo neurone nell’ultimo livello (dimostrare questo risultato non è difficile, ma so che le dimostrazioni non vi appassionano). Ma possiamo fare di meglio ed enunciare un paio di risultati più generali (anch’essi dimostrabili, ma vi risparmio la faticaccia).

Per ogni d esiste una ANN di profondità 2 (e quindi con un solo livello nascosto) in grado di implementare qualsiasi funzione da {-1,1}d a {-1,1}. Ciò significa che si possono rappresentare tutte le funzioni booleane.

Questo è già interessante di per sé, ma passiamo al secondo.

Per ogni ε>0 esiste una ANN che implementa una f tale che, dato un input x, l’output sia in [f(x)-ε,f(x)+ε]. Ciò significa che le ANN sono approssimatori universali.

Se ipotizziamo che un problema possa essere espresso sotto forma di modello matematico, allora possiamo utilizzare una ANN per risolvere questo problema, dato che può rappresentare una funzione in grado di risolverlo con una precisione ε a piacere. Se poi ipotizziamo che tutti i problemi possano essere rappresentati da un modello matematico, abbiamo fatto bingo: le ANN possono risolvere qualsiasi problema, anche trovare la risposta alla domanda fondamentale sulla vita, l’universo e tutto quanto. Fantastico no? Ovviamente c’è un MA, ed è un MA grosso come una montagna.

Ecco il MA

Esiste un terzo risultato.

Se d è la dimensione dell’input, il numero di neuroni necessari per la costruzione della ANN è esponenziale in d.

E quindi? E quindi il problema è spiegato nell’articolo sulla complessità degli algoritmi, che vi invito a leggere, ma che vi riassumo qui brevemente: portare a termine l’elaborazione di una ANN è un problema NP-completo. Esiste una soluzione al problema ma per trovarla vi serve qualche milione di anni, sette milioni e mezzo per essere precisi.

Ma allora perché queste reti sono così famose e così largamente utilizzate? Famose da decenni, ma utilizzate da pochi anni: per poterle utilizzare è richiesta una grossa capacità di calcolo, resa disponibile solo dalla tecnologia degli ultimi anni. Inoltre le reti attualmente in uso sono di modeste dimensioni e utilizzate insieme ad altre tecniche che permettono di risparmiare tempo e fatica, senza contare il fatto che se un problema è risolvibile con un modello più semplice, di solito si sceglie quello anche se è meno preciso.