![]() | ![]() |
|
|
La rete in esame è una memoria autoassociativa realizzata sul modello di Hopfield: una rete neuronale completamente connessa con matrice delle connessioni simmetrica e modalità di attivazione asincrona. I neuroni che compongono la rete sono neuroni binari a soglia (attualmente q=0) con funzione di uscita
dove a rappresenta lo stato di attivazione ed è pari a:
e wi è un numero intero che indica se il canale è eccitatorio (wi>0) o inibitorio (wi<0).
Lo stato della rete viene espresso mediante un vettore di + e - delle dimensioni pari alla rete neurale (quindi al numero di neuroni desiderati). Il recupero dei ricordi avviene applicando la seguente equazione di evoluzione della rete a partire da un vettori di ingresso:
Dove xi' e lo stato successivo del neurone xi attualmente in esame. Essendo l'attivazione asincrona ad ogni passo viene cambiato lo stato di un solo neurone: quello che garantisce una maggiore minimizzazione dell'energia associata allo stato del sistema. Tale modalità di attivazione garantisce una convergenza rapida verso lo stato più vicino allo stato di sonda come distanza di Hamming. Il numero di memorie assimilabili dalla rete è pari a:
dove n è il numero di neuroni definito inizialmente.
Il modello di Hopfield è affetto dalla comparsa di memorie spurie: uno stato memorizzato e lo stato complementare (ad esempio + + - 222d33c + e - - + -) vengono associati al medesimo ricordo.
è la variabile che contiene le dimensioni della rete, viene definita a tempo di esecuzione non appena si chiama il costruttore della classe ed è utilizzata ogni qual volta è necessario sapere le dimensioni della rete.
la matrice dei pesi delle connessioni viene creata dinamicamente non appena diventano note le dimensioni della rete. La matrice viene realizzata mediante Pesi che è un puntatore a puntatore di interi e punta ad un array di puntatori a interi che a loro volta puntano ciascuno ad un nuovo array di interi. Gli array sono ovviamente di dimensione size. La matrice viene creata ed inizializzata dal costruttore.
il costruttore della classe Cerebro, dim sono le dimensioni della rete neurale; si occupa principalmente della creazione della matrice dei pesi e della sua inizializzazione a zero.
il costruttore di copia; entra in gioco quando si vuole copiare una rete neurale sopra a un'altra. Vengono quindi acquisite le dimensioni e i valori della classe individuata dalla matrice matrix.
il distruttore: dealloca inizialmente i "size" vettori di interi per poi deallocare il vettore di puntatori ad interi.
Provvede ad impiantare un ricordo nella rete. Il controllo sul numero di ricordi che possono essere ancora impiantati nella rete è lasciato all'interfaccia, mentre di competenza della funzione membro, è la verifica che il ricordo non sia già presente nella rete (il controllo è realizzato mediante la chiamata della funzione membro sonda). In tal caso l'impianto non ha luogo e la funzione ritorna il valore booleano F. Viceversa se la rete non contiene tale ricordo la matrice dei pesi viene aggiornata e la funzione ritorna il valore booleano T.
Come la precedente funzione, si occupa dell'impianto di un ricordo nella rete neurale. È possibile però, mediante la variabile di overrun (attiva con valore T) costringere la rete ad accettare un ricordo anche se è già presente.
Provvede ad eliminare un ricordo dalla rete neurale, previa analisi della effettiva consistenza del ricordo nella rete mediante la funzione membro sonda. Ritorna un booleano: T se l'espianto ha effettivamente luogo, F altrimenti. Ovviamente, come effetto collaterale, la matrice dei pesi viene aggiornata.
Si comporta come la funzione membro precedente con l'unica differenza che, mediante la variabile di overrun (attiva con valore T), è possibile costringere la rete neurale ad effettuare un espianto anche se il ricordo non trova una corrispondenza nelle memorie della rete. Restituisce, come al solito, T se l'espianto ha luogo, F altrimenti (la variabile di overrun è bassa e si sta tentando di espiantare un vettore che non rappresenta effettivamente un ricordo).
Calcola e ritorna l'energia del pensiero fornito alla rete (un vettore di + e -), secondo la nota formula:
Calcola lo stato successivo del vettore pensiero in ingresso secondo le modalità specificate nel paragrafo 1. La funzione membro calcola inizialmente un vettore chiamato intermedio che contiene lo stato successivo della rete neurale calcolato in modalità sincrona. Successivamente genera una serie di candidati allo stato successivo vero e proprio. Ciascun candidato può differire dal pensiero solo per un bit, i bit che possono essere cambiati sono ovviamente solo quelli che differenziano il pensiero di ingresso da intermedio. Viene calcolata la funzione energia per ciascun candidato e infine viene promosso a stato successivo il candidato che ha associata l'energia minore.
Dato un vettore pensiero in ingresso la funzione membro sonda cerca, mediante continue chiamate alla funzione membro statosucc, il ricordo più vicino (come distanza di Hamming, data l'implementazione) al pensiero fornito in ingresso. La funzione ritorna tale ricordo. Attenzione: se la rete neurale è vuota, la rete di Hopfield, per sua natura, associa ad ogni pensiero il ricordo ++++.+, anche se esso non è stato inserito dall'utente. Tale meccanismo è rispettato da questa implementazione della rete, il controllo sulla reale consistenza del ricordo viene affidato all'interfaccia che si occupa di rispondere all'utente che la rete non può essere sondata se non si inseriscono prima dei ricordi.
Provvede ad eliminare tutti i ricordi dalla rete reinizializzando a zero la matrice dei pesi.
Restituisce le dimensioni della rete neurale.
Restituisce il valore dell'elemento (i,j) della matrice dei pesi.
La rete neurale è stata implementata mediante l'uso delle classi. Abbiamo definito una classe modello vector (vettore.mod) che ci consente l'uso di un vettore di caratteri di dimensioni definibili a tempo di esecuzione e una classe Cerebro (neural.h e neural.cc) che si appoggia alla prima e realizza il tipo di dato astratto Rete Neurale di Hopfield. Mediante l'interfaccia (interfac.cc) è possibile utilizzare la rete neurale. Le dimensioni della rete sono definibili dinamicamente all'inizio delle esecuzione del programma. Si riporta di seguito il codice delle classi realizzate
#include <fstream.h>
enum booleano ;
template <class type>
class vector
template <class type>
vector<type>::vector(int n)
template <class type>
vector<type>::vector(const vector& v)
template <class type>
vector<type>::~vector()
template <class type>
type& vector<type>::operator[](int i) const
else
return p[i];
template <class type>
type& vector<type>::operator[](int i)
else
return p[i];
template <class type>
vector<type>& vector<type>::operator=(const vector& v)
else
for (int i=0; i<size; i++)
p[i]=v.p[i];
return *this;
template <class type>
vector<type>& vector<type>::operator=(type s)
template <class type>
booleano vector<type>::operator==(const vector& v) const
else
template <class type>
booleano vector<type>::operator!=(const vector& v) const
else
template <class type>
int vector<type>::lunghezza() const
neural.h
#include "vector.mod"
#include <fstream.h>
class cerebro
neural.cc
#include "neural.h"
const int maxint=255;
cerebro::cerebro(int dim)
size=dim;
pesi=new int*[dim];
for (int i=0; i<dim; i++)
pesi[i]= new int[dim]; //creazione della matrice
for (int i=0; i<size; i++) //inizializzazione della matrice a 0
for (int j=0; j<size; j++)
pesi[i][j]=0;
cerebro::cerebro(const cerebro& matrix) //costruttore di copia
cerebro::~cerebro()
int cerebro::energia(const vector<char> pensiero)
// controllo dimensionale
int value=0,x;
for (int i=0; i<size-1; i++)
for (int j=i+1; j<size; j++)
return value;
vector<char> cerebro::statosucc(const vector<char> pensiero)
// controllo dimensionale
int valore,somma;
vector<char> intermedio(size);
for (int i=0; i<size; i++)
//intermedio contiene lo stato successivo in modalita` sincrona
if (somma>=0) intermedio[i]='+';
else intermedio[i]='-';
}
if (intermedio==pensiero) return pensiero;
else
else appoggio[i]=maxint;
}
int minimo,index=0;
minimo=appoggio[0];
for(int i=1; i<size; i++)
if(appoggio[i]<minimo)
candidato=pensiero;
candidato[index]=intermedio[index];
return candidato;
}
vector<char> cerebro::sonda(const vector<char> pensiero)
// controllo dimensionale
vector<char> swap1(size), swap2(size);
swap1=pensiero;
do
while (swap1!=swap2);
return swap1;
booleano cerebro::impianta(const vector<char> ricordo)
// controllo dimensionale
if (sonda(ricordo)!=ricordo)
return T;
}
return F;
booleano cerebro::impianta(const vector<char> ricordo, const booleano overrun)
// controllo dimensionale
if ((overrun==T) || (sonda(ricordo)!=ricordo))
return T;
}
return F;
booleano cerebro::espianta(const vector<char> ricordo)
// controllo dimensionale
if (sonda(ricordo)!=ricordo) return F;
else
return T;
}
booleano cerebro::espianta(const vector<char> ricordo, const booleano overrun)
// controllo dimensionale
if ((overrun==F) && (sonda(ricordo)!=ricordo)) return F;
else
return T;
}
void cerebro::lobotomia()
int cerebro::dimensione()
int cerebro::peso(int i, int j)
4. Interfaccia per l'utilizzo della Rete Neurale
Interfac.cc è un possibile programma di gestione della classe Cerebro precedentemente realizzata. Le possibilità dell'interfaccia sono le seguenti:
Impianto di un ricordo alla rete
Si occupa di gestire l'impianto di ricordi nella rete, verificando se si sta raggiungendo un numero critico di ricordi (utilizzando la var inter nricordi) e chiedendo all'utente se si vuole effettivamente procedere nell'impianto. Se l'impianto fallisce a causa della verificata presenza dello stesso ricordo che si vuole impiantare nella rete, anche in questo caso il programma chiede all'utente il permesso di procedere ugualmente.
Espianto di un ricordo dalla rete
Gestisce l'espianto dei ricordi, verificando se effettivamente ci sono ricordi da espiantare (sempre mediante la var intera nricordi) e se il pensiero da espiantare rappresenta effettivamente un ricordo per la rete. È comunque possibile obbligare la rete ad espiantare uno stato che essa stessa non considera un ricordo.
Sonda di un pensiero
Chiama la funzione membro sonda per cercare il ricordo più vicino al pensiero in ingresso e lo stampa a video.
Lobotomizzare la rete
Chiama la funzione membro lobotomia per l'azzeramento della matrice dei pesi.
Stampare la matrice dei pesi
Stampa a video la matrice dei pesi della rete neurale.
Calcolare l'energia di un pensiero
Stampa a video l'energia di un pensiero fornito dall'utente.
Sonda passo passo
Mediante chiamate successive della funzione membro statosucc calcola e stampa a video il percorso sul bacino di attrazione della rete neurale di un pensiero verso il ricordo più vicino.
Numero di ricordi impiantati
Stampa a video il numero di ricordi attualmente impiantati nella rete. Ogni ricordo è associato a due stati memorizzati (l'originale ed il complementare) a causa della presenza di memorie spurie.
Uscire
Esce dal programma.
#include "neural.h"
#include <iostream.h>
#include <new.h>
#include <math.h>
void menu()
void main()
cout << " Inserire il ricordo da impiantare (+/-): ";
for (int i=0; i<dim; i++) cin >> ricordo[i];
if (nricordi==0)
if (rete->impianta(ricordo)==T)
else
}
break;
case 2: cout << "\n Inserire il ricordo da espiantare (+/-): ";
for (int i=0; i<dim; i++) cin >> ricordo[i];
if (rete->espianta(ricordo)==T)
else
}
break;
case 3: cout << " Inserire il pensiero da sondare (+/-): ";
for (int i=0; i<dim; i++) cin >> pensiero[i];
ricordo=rete->sonda(pensiero);
cout << " Il ricordo più vicino al pensiero immesso è \n";
cout << " ";
for (int i=0; i<dim; i++)
cout << ricordo[i];
cout << "\n";
break;
case 4: cout << " La lobotomia eliminerà tutti i ricordi dalla rete \n";
cout << " Procedere (s/n)? ";
cin >> carattere;
if (carattere=='s')
break;
case 5: cout << " Matrice dei pesi: \n";
for (int i=0; i<dim; i++)
break;
case 6: cout << " Inserire il pensiero di cui si vuole calcolare l'energia: ";
for (int i=0; i<dim; i++)
cout << " L'energia associata è: " << rete->energia(pensiero) << "\n";
break;
case 7: cout << " Inserire un pensiero (+/-): ";
for (int i=0; i<dim; i++)
do
while (carattere=='s');
break;
case 8: cout << " Attualmente sono presenti " << nricordi << " ricordi \n";
break;
case 9: fine=T; break; // esci
default: break;
}
}
while (fine==F);
cout << "\n Beh... S'è fatto tardi...\n";
Privacy |
Articolo informazione
Commentare questo articolo:Non sei registratoDevi essere registrato per commentare ISCRIVITI |
Copiare il codice nella pagina web del tuo sito. |
Copyright InfTub.com 2025