Caricare documenti e articoli online 
INFtub.com è un sito progettato per cercare i documenti in vari tipi di file e il caricamento di articoli online.


 
Non ricordi la password?  ››  Iscriviti gratis
 

RELAZIONE SUL PROGETTO DI UNA - RETE NEURALE BASATA SUL MODELLO DI HOPFIELD

tecnica



Relazione sul progetto di una

Rete Neurale basata sul modello di Hopfield




1. Descrizione della Rete


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.

2. Descrizione della classe Cerebro e delle sue principali funzioni membro


Parte privata

int size

è 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.

int** pesi

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.


Parte pubblica

cerebro(int dim)

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.

cerebro(const cerebro& matrix)

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.

~cerebro( )

il distruttore: dealloca inizialmente i "size" vettori di interi per poi deallocare il vettore di puntatori ad interi.

booleano impianta(const vector<char> ricordo)

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.

booleano impianta(const vector<char> ricordo, const booleano overrun)

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.

booleano espianta(const vector<char> ricordo)

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.

booleano espianta(const vector<char> ricordo, const booleano overrun)

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).

int energia(const vector<char> pensiero)

Calcola e ritorna l'energia del pensiero fornito alla rete (un vettore di + e -), secondo la nota formula:

vector statosucc(const vector<char> pensiero)

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.

vector sonda(const vector<char> pensiero)

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.

void lobotomia( )

Provvede ad eliminare tutti i ricordi dalla rete reinizializzando a zero la matrice dei pesi.

int dimensione( )

Restituisce le dimensioni della rete neurale.

int peso(int i,int j)

Restituisce il valore dell'elemento (i,j) della matrice dei pesi.


3. Implementazione della Rete Neurale


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


vettore.mod


#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.

Interfac.cc

#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


Hits: 5713
Apprezzato: scheda appunto

Commentare questo articolo:

Non sei registrato
Devi essere registrato per commentare

ISCRIVITI



Copiare il codice

nella pagina web del tuo sito.


Copyright InfTub.com 2024