NEURBOOK_HOME
INTRODUZIONE
CAPITOLO 1 * ESEMPIO DI MEMORIA ASSOCIATIVA
CAPITOLO 2 * RETI NEURALI ERROR BACK PROPAGATION
CAPITOLO 3 * APPLICAZIONI PRATICHE DI UNA RETE NEURALE EBP
CAPITOLO 4 * RETI NEURALI AUTOORGANIZZANTI
CAPITOLO 5 * FUZZY LOGIC LA TEORIA DEL RAGIONAMENTO SFUMATO
CAPITOLO 6 * NEURFUZZ 1.0
CAPITOLO 7 * GUIDA AL FLOPPY DISK
CAPITOLO 8 * GUIDA AL SOFTWARE
BIBLIOGRAFIA

Neurfuzz 1.0

Generatore di codice c per reti
neurali error back propagation
e fuzzy systems

Introduzione

Neurfuzz è un tool composto da due programmi complementari, "Neuronx" e "Fuzzkern" che hanno, rispettivamente, le funzioni di generatore di reti neurali error back propagation e fuzzy systems. Neuronx è un programma in grado di addestrare una rete neurale ebp prelevando i dati relativi al training set da un file in formato ascii. Raggiunto il target error si può passare alla fase di test utilizzando l'apposito ambiente integrato. Successivamente, è possibile generare un file in codice c che costituisce la rete neurale addestrata e può comunicare con altri programmi tramite files, ma può anche essere integrato come funzione all interno di altri programmi (fig.1). Fuzzkern permette di generare programmi in codice c che contengono il "reasoning engine" di un sistema fuzzy. Tali programmi devono essere utilizzati in combinazione con reti neurali generate con Neuronx utilizzando l opzione delle interfacce fuzzy: in pratica le operazioni di fuzzificazione e defuzzificazione vengono eseguite all interno della rete, mentre la esecuzione delle regole avviene all interno del "reasoning engine". In questo modo è possibile, anche grazie alla architettura modulare di tipo object oriented del sistema, creare sistemi ibridi contenenti strati alternati delle tecnologie fuzzy e neuronale(fig.2). Le reti generate hanno due strati hidden che possono avere fino a 100 neuroni ciascuno e un massimo di 100 inputs e 100 outputs. Neuronx può girare su un 286 con 560 kb di memoria disponibile per programmi, facilmente ottenibile su DOS 6.0; la presenza del coprocessore matematico 287 accelera notevolmente il processo di apprendimento.


DOWNLOAD NEURFUZZ 1.0
from
Walnut Creek CDROM







ADDESTRAMENTO

La prima cosa che bisogna analizzare è il formato che devono avere i dati nel training file che, deve essere un normale file ascii organizzato con gli esempi in sequenza. Ciascuno è composto dalla sequenza degli input e degli output, come mostrato in tabella1. I valori devono essere normalizzati, cioè portati alla scala 0.0 -1.0 , e ciò è fattibile anche usando il tool "data normalization" presente nel menu alla voce "data preprocessing". Se si ha un file di dati non normalizzato, bisogna inserire i valori minimo e massimo contenuti nel file ed eseguire la normalizzazione. Preparato il file normalizzato, è necessario definire il numero degli inputs, degli outputs(tipici del problema) e il numero dei neuroni di ognuno dei due strati hidden. Fatta questa operazione si puo passare alla fase di addestramento vero e proprio con l'opzione "ebp learning" che chiederà il nome del training file, il numero degli esempi in esso contenuti, la costante di apprendimento(è opportuno scegliere valori intorno a 0.5) e il target error(un errore 0.05 rappresenta un errore del 5% e può andare molto bene in numerose applicazioni). Durante la fase di addestramento vedrete l'errore, prodotto dalla rete in esecuzione, diminuire ad ogni epoca a causa delle correzioni effettuate sui pesi dall'algoritmo di retropropagazione degli errori. In un primo momento, potreste vedere che l'errore cresce anzichè diminuire: questo fenomeno è dovuto ad uno stato confusionale che la rete ha inizialmente a causa della inizializzazione random dei valori dei pesi. Quando la rete raggiunge il target error ferma l'addestramento e, a questo punto, è possibile testare la rete con degli esempi.

tabella 1

0.2 input1 esempio 1

0.3 input 2

0.5 output 1

0.1 input 1 esempio 2

0.6 input 2

0.7 output1

sequenza dei dati nel file di addestramento



AMBIENTE DI TEST

In fase di test la rete legge i dati di input dal file NET.IN e scrive i dati di output nel file NET.OUT. Scegliendo la opzione "test" eseguite la rete con i dati contenuti nel file suddetto e modificateli da interfaccia dopo ogni esecuzione(fig.3). Potete usare dati che non erano presenti nel training set, testando il potere di generalizzazione della rete in interpolazione e in estrapolazione. Se siete soddisfatti, potete scegliere di salvare in file il contenuto dei pesi della rete che potrete ricaricare in un secondo tempo per fare aggiornamenti con un nuovo training set migliorato o aggiornato, senza dover partire da zero: potete fare queste operazioni con i comandi "save weight on file" e "load weight from file". A questo punto è possibile generare il codice c .

GENERAZIONE CODICE C

Si può immediatamente generare il codice c relativo alla rete neurale addestarata scegliendo se deve essere un programma indipendente o una funzione da inserire dentro altri programmi. In ogni caso, una volta scelto il nome del file (senza estensione), verranno generati i file "nome.c" che, contiene il codice,"nome.h", che è un header file che contiene il know how della rete. Sia che si abbia una funzione o un programma indipendente la rete comunica tramite i file "nome.in" e "nome.out". Non è possibile inserire più di una rete neurale come funzione all'interno di un programma a causa della definizione globale di alcuni dati, ma sarebbe comunque difficile farlo a causa della dimensione delle matrici dei pesi. Dovendo costruire un sistema complesso, comprendente più reti neurali, è consigliabile realizzare programmi indipendenti da collegare tramite files batch o tramite system() da qualunque linguaggio. Un esempio di file batch che utilizza tale sistema è rappresentato nel listato_1.

ADDESTRAMENTO CON ALGORITMO GENETICO

Si puo addestrare la rete utilizzando il tipico algoritmo di retropropagazione dell errore, ma anche tramite un algoritmo che sfrutta i principi dell evoluzione di Darwin. Gli algoritmi genetici sono ampiamente utilizzati nella moderna intelligenza artificiale per risolvere problemi di ottimizzazione. La base fondamentale di un algoritmo genetico è una popolazione di individui (cromosomi) composti, ciascuno, da un certo numero di geni che rappresentano caratteri dell individuo. Un individuo può avere caratteri più adatti alla soluzione del problema di un altro: si dice che la "fitness function" per quell' individuo porta ad un valore più vicino alla soluzione. Per fitness function si intende una funzione che lega i caratteri del cromosoma(le variabili indipendenti nel problema) alla variabile che rappresenta la soluzione del problema. Un algoritmo genetico deve calcolare la fitness function per ogni individuo della popolazione e salvare gli individui migliori . Partendo da questi individui, deve generare una nuova popolazione tramite gli operatori "crossover" e "mutation"che, rispettivamente, scambiano geni tra cromosomi e creano piccole mutazioni casuali su alcuni geni dei cromosomi. Viene ricalcolata la fitness function per ogni individuo della nuova popolazione e salvati gli individui migliori. Questo ciclo viene ripetuto un numero molto elevato di volte creando sempre nuove "generazioni di individui". Nel nostro caso, un individuo o cromosoma è rappresentato dal vettore contenente tutti i pesi dei collegamenti tra gli strati neuronali della rete e ogni singolo peso rappresenta un gene del cromosoma. Ogni individuo viene testato e, in questo caso, la fitness function coincide con l'esecuzione della rete stessa Gli individui migliori sono quelli che portano ad un errore globale più vicino al target . Si parte con tre individui e si salva il migliore e, come sopra esposto, si crea da esso una nuova popolazione di tre individui con gli operatori crossover e mutation, lasciando invariato un individuo per impedire possibili involuzioni. Questo ciclo viene ripetuto fino al raggiungimento del target error. Un addestramento con algoritmo genetico è utile su livelli molto bassi di errore della rete per due motivi: il primo è il fatto che un algoritmo genetico può superare i minimi locali e, il secondo è che su livelli alti di errore il classico algoritmo a retropropagazione dell'errore è molto efficente mentre su livelli di errore bassi, cioè quando ci si avvicina al minimo assoluto (o comunque ad un minimo), tale algoritmo produce avvicinamenti al target molto lenti(ricordate la tecnica della discesa del gradiente e il fatto che la derivata di una funzione su un punto di minimo è nulla?)



Per questo motivo l'apprendimento con algoritmo genetico può partire solamente da errori inferiori a 0.5, perchè per errori maggiori la retropropagazione degli errori risulta più efficiente. Si può anche utilizzare un tool ibrido che inizia l'addestramento con algoritmo ebp e continua con algoritmo genetico, automaticamente, in prossimità del 10% di distanza dal target. Un diagramma di flusso dell algoritmo genetico è rappresentato in fig.4.



TEST DISTRIBUZIONE DATI

Si può effettuare un test sulla distribuzione dei dati contenuti nel training set al fine di verificare se esistono concentrazioni di dati non uniformemente distribuite sul range di ciascun input. Una disuniforme distribuzione dei dati potrebbe compromettere la capacità di generalizzazione della rete, anche dopo un risultato soddisfacente in fase di addestramento. Scegliendo la opzione "data distribution test" contenuta in "data preprocessing", si ottiene una relazione di distribuzione per ogni coppia di input dove il range di ogni input viene diviso in cinque regioni come mostrato in fig.5. Una corretta distribuzione si ha quando la quantità di dati è equamente distribuita in ogni casella per ogni coppia di input. Tramite questo test è possibile anche scoprire una possibile relazione tra due inputs: ciò rappresenterebbe un appesantimento inutile per il training della rete ed è conveniente eliminare una delle variabili correlate.

INTERFACCE FUZZY

Come precedentemente accennato, esiste la possibilità di definire sia input che output della rete in formato fuzzy. Questo significa che la rete accetta dati in input in formato fuzzy ed effettua una defuzzificazione, sulla base delle classi definite dall utente, per presentare agli input effettivi dei valori numerici. Si può scegliere anche la fuzzificazione degli output che prevede la operazione inversa: i valori numerici in uscita vengono trasformati in formato fuzzy, secondo le classi definite dall utente, per ogni output. Defuzzificazione in ingresso e fuzzificazione in uscita sono indipendenti, cioè possono essere selezionati separatamente. Il formato di rappresentazione dei dati fuzzy è il seguente:

input /output n

0 classe 0

.34 degree of membership

$ separatore di classe

1 classe 1

.56 degree of membership

& separatore di input/output(nuovo input/output)

1 classe 1

.45 degree of membership

$ separatore di classe

2 classe 2

.20 degree of membership

& separatore di input/output

Come vedremo è possibile collegare reti neurali con queste interfacce con programmi "fuzzy reasoning engine" generati da Fuzzkern che utilizzano, naturalmente, le stesse convenzioni di input / output. La fuzzificazione avviene attraverso funzioni "circolari" con uso di funzioni seno e coseno, anzichè le classiche triangolari/trapeziodali, e per questo motivo sono state chiamate "bubble". Le classi circolari scendono verso gli estremi in modo non lineare(fig.6). La defuzzificazione avviene attraverso la regola del "center of gravity" semplificata che abbiamo visto nel capitolo dedicato al ragionamento sfumato.



TEST SUL POTERE DI GENERALIZZAZIONE

Come ormai ben sapete, una delle caratteristiche salienti delle reti neurali è quella di godere di una certa elasticità di ragionamento che consente di avere risposte significative anche fuori dal training set. Più precisamente, possiamo dare come input alla rete valori non presenti nel training set chiedendole di effettuare una interpolazione o una estrapolazione. Il problema in questione è molto legato alla possibilità di avere un "overtraining" della rete, cioè un addestramento troppo incisivo. Effettivamente quando si addestra una rete neurale raggiungendo errori molto piccoli si rischia di insegnare alla rete a riconoscere il "rumore" , per cui dati estranei al training set possono diventare dati estranei in senso assoluto: la rete in questo modo ha perso potere di generalizzazione. Bisogna tenere presente che una rete neurale non è un preciso sistema di calcolo ma sistema di calcolo impreciso anche se intelligente: quando addestriamo una rete neurale, dobbiamo trovare una soluzione bilanciata tra la necessità di raggiungere un errore piccolo sul training set e la richiesta di potere di generalizzazione che, comunque, dipende anche dalla validità dei dati scelti per costruire il training set. Normalmente un minore numero di connessioni sinaptiche in rapporto al numero di esempi del training set induce una maggiore capacità di generalizzazione. Questo è dovuto al fatto che la rete non ha abbastanza memoria per "imparare" anche il "rumore". Una tecnica utilizzata è quella di eliminare connessioni sinaptiche che subiscono scarse variazioni durante il processo di addestramento, attuando cosi una ottimizzazione " a finestre" del complesso delle connessioni sinaptiche. Il programma Neurfuzz nasce con obbiettivi sperimentali e segue, in questo caso, una strada completamente differente, che ha dato risultati positivi solo in certe condizioni, con particolari training sets. Questa opzione è rimasta nel programma sebbene non sia stata validata in alcun contesto definito e specificabile. La procedura utilizzata in questa opzione sperimentale è descritta di seguito. Per ogni epoca, a partire da un certo errore (che può essere scelto dall utilizzatore), viene calcolato l'errore globale, ottenuto con il validation set, e confrontato con quello ottenuto con il training set: se esiste una differenza percentuale maggiore di quella scelta dall utente, il numero dei neuroni degli strati hidden viene automaticamente incrementato. Dopo questa procedura, viene effettuata una operazione molto particolare che, consiste in un superficiale "lavaggio del cervello", ottenuto con piccole variazioni casuali e distribuite sui pesi degli strati hidden. Questa operazione ha come primo effetto evidente, quello di elevare notevolmente l errore della rete, ma errori molto piccoli vengono nuova mente raggiunti in tempi brevissimi(effettivamente è rimasta una matrice profonda dell'addestramento precedente) e con una "ridistribuzione" del know how su tutti i neuroni, indispensabile per il raggiungimento dello scopo.
Il diagramma di flusso di tutta la operazione è rappresentato in
fig.7.

TEST SULLA RESISTENZA AL RUMORE

Si possono effettuare due operazioni che simulano "guasti neuronali" al fine di verificare la robustezza della rete basata sul fatto che l'informazione è realmente frammentata e distribuita sul complesso dei collegamenti sinaptici. L' operazione di "lobotomy", ovvero asporatazione di una piccola parte del cervello o, diverse operazioni di "microchirurgia" su singole connessioni sinaptiche, possono essere effettuate a questo scopo.

SIMULATED ANNEALING(*):
REGIME TERMICO DINAMICO

Uno dei problemi che si possono presentare nell addestramento di una rete neurale è quello della caduta in un minimo locale (rimando al capitolo sulla retropropagazione dell errore). Uno degli espedienti che sono stati sperimentati per superare tale problema è quello di adottare una legge di tipo probabilistico del neurone, tale che le variazioni di attivazione vengano accettate con un certo grado di probabilità crescente nel tempo. Facciamo un esempio che dia un immagine "fisica" del problema: immaginate di avere un piano di plastica deformato con "valli" e "monti" di varie estensioni e profondità, e di porvi sopra una pallina con l'obbiettivo di farla cadere nella valle più profonda(minimo assoluto). Molto probabilmente la pallina cadrà nella valle più vicina al punto in cui la abbiamo messa che potrebbe non essere la valle più profonda. Il processo di simulated annealing consiste nel muovere il piano di plastica in modo che la pallina lo percorra superando monti e valli e diminuire la intensità del movimento gradualmente fino a zero. Molto probabilmente, la pallina rimarrà nella valle più profonda dalla quale, a un certo punto, il movimento non sarà più sufficiente a farla uscire. Nella nostra rete tutto questo non viene realizzato con un vero algoritmo probabilistico, ma si utilizza una legge di attivazione a sigmoide modificata che contiene un parametro "temperatura":

A=1/(1+e**P/t)

A=valore di uscita del neurone

P=valore di attivazione del neurone(sommatoria degli ingressi)

t=temperatura

Nella cosiddetta Macchina di Boltzmann, che fa uso di una legge di attivazione probabilistica, la temperatura viene normalmente fatta diminuire gradualmente nel tempo. Nel nostro programma la temperatura viene correlata alla differenza tra errore della rete e target error in modo che diminuisca con il diminuire di questa differenza. In principio la sigmoide ha una pendenza molto lieve garantendo risposte di output poco intense a variazioni di input anche elevate; in seguito la sigmoide si avvicina sempre più al gradino per cui il neurone ha risposte intense a piccole variazioni di input(fig.8). Con questo sistema, in questo specifico programma, è possibile avere risultati molto interessanti nella risoluzione di certi problemi e avere risultati negativi con altri tipi di problemi. Ciò dipende, effettivamente, da come si presenta la "superficie" ottimale dei pesi per la risoluzione del problema stesso. Utilizzando questo processo, si può notare un mantenimento più lungo di livello di errore molto elevato, che talvolta (problema adatto a questo tipo di soluzione), scende a valori estremamente bassi in tempi rapidissimi(fig.9). Bisogna precisare che, la Macchina di Boltzmann nulla ha in comune con questa rete e, il principio del Simulated Annealing è stato, in questo contesto, applicato con modalità differenti(**).



THERMOSHOCK

Questa funzione è orientata a risolvere il problema dei minimi locali, come quella precedente, ma con un criterio differente. Viene effettuato un test sulla derivata dell'errore e viene effettuato uno shock termico sulla rete se l'errore ha una discesa troppo lenta o ha una oscillazione con media costante ed è lontano dal target error. Lo shock termico viene realizzato tramite una variazione casuale dei pesi della rete. Ritengo che siano veramente pochi i problemi che possano trarre beneficio da questa utility che, comunque, resta interessante come curiosità didattica.

FUZZKERN : DEFINIZIONE DELLE REGOLE
DI UN REASONING ENGINE

Fuzzkern permette la costruzione di programmi che effettuano la scansione ed esecuzione di regole tipo "if (x is in class a) then y is in class b". Tutto ciò ha senso solamente se, in input, esistono dati in formato fuzzy e se, in output, esiste qualcosa in grado di capire dati in formato fuzzy. Questi programmi(generati da Fuzzkern) devono infatti essere interfacciati con reti neuronali create con Neuronx utilizzando la defuzzificazione degli input e la fuzzificazione degli output. Il programma chiede in sequenza le regole che devono essere inserite nel rules_base ed esiste la possibilità di inserire degli operatori di tipo and tra una regola e la successiva:

if ((x1is in class a)&&(x2 is in class c)) then y1 is in class e

Una limitazione durante la stesura delle regole è che, un eventuale gruppo di regole linkate con operazione "and" deve essere inserito prima di regole libere che condividano la stessa conseguenza. Questo è dovuto al fatto che il calcolo della forza della regola (e quindi il degree of membership nella conseguenza), nel caso di regole and_linkate, viene effettuato tramite una operazione di fuzzy_and ( scelta del valore più basso), mentre nel caso di due regole non vincolate da "and" si effettua una operazione di fuzzy_or(scelta del valore più elevato): il bug consiste nella mancanza di una traccia che permetta un feedback di verifica sul and_link flag delle regole. In una successiva versione questo problema potrebbe essere corretto, ma per il momento la presenza di regole and_linkate dopo regole libere che esprimano la stessa conseguenza può alterare il calcolo della "strenght of the rule".

LISTATO 1

input (programma lettura dati input da dispositivo o file e scrittura su file network1.in)

network1 (fuzzy out network)

ren network1.out sysfuzz.i n (trasferimento dati)

sysfuzz1 (fuzzy reasoning engine)

ren sysfuzz.out network2.in (trasferimento dati)

network2 (fuzzy in network)

output (programma di lettura dati da file network2.out e scrittura su dispositivo o file)

(*) SIMULATED ANNEALING: significa ricottura simulata e si ispira al processo di ricottura dei vetri di spin("spin glasses"). Un vetro di spin è un metallo contenente delle impurità di un altro metallo in percentuali molto basse ed ha caratteristiche magnetiche particolari. Un metallo puro può essere ferromagnetico(ferro) o non ferromagnetico(cromo). I metalli ferromagnetici hanno tutti gli atomi con lo stesso momento magnetico o spin(vettori con stessa direzione e stesso verso). Un metallo non ferromagnetico ha tutti gli atomi adicenti con spin in posizione di equilibrio(stessa direzione ma verso differente). Portando un metallo al di sopra di una certa temperatura critica, gli spin degli atomi assumono direzioni e versi casuali(un metallo ferromagnetico perde le sue proprietà magnetiche); il raffreddamento del metallo al di sotto della temperatura critica porta tutti gli spin verso una posizione di equilibrio(minima energia) ferromagnetico o non. Nei vetri di spin il raffreddamento congela, invece, gli spin in uno stato caotico, pertanto, a bassa temperatura, non esiste uno stato di minima energia, ma molti minimi relativi. Un raffreddamento lento permette di raggiungere un minimo ottimale(più vicino alla energia minima assoluta).

(**) MACCHINA DI BOLTZMANN: Si tratta di una rete neurale derivata dalla rete di Hopfield che, attraverso opportune formule di apprendimento, converge verso uno stato di equilibrio compatibile con i vincoli del problema. Può essere una memoria associativa ma è impiegata, in particolare, per la risoluzione di problemi di ottimizzazione, in cui la fase di apprendimento si basa sulla dimostrazione(di Hopfield) che, alla rete è associata una funzione "energia" da minimizzare rispettando i vincoli del problema(ottimizzazione). La Macchina di Boltzmann è sostanzialmente una rete di Hopfield in cui i neuroni adottano una legge di attivazione di tipo probabilistico: se da uno stato S(t) la rete evolve verso uno stato S(t+1) allora, questo nuovo stato viene sicuramente accettato se la energia della rete è diminuita (o è rimasta invariata), altrimenti viene accettato, ma solo con una certa probabilità che, aumenta al diminuire della temperatura(figg.10/11). Questo sistema consente il raggiungimento di una soluzione molto vicina all ottimo assoluto nei problemi di ottimizzazione, secondo la teoria precedentemente esposta. La nostra rete non è una memoria associativa ma una rete multistrato "feed-forward"(propagazione del segnale da input verso output attraverso gli strati intermedi), utilizzata principalmente per estrazione di funzioni matematiche non conosciute da esempi input/output(si può comunque utilizzare anche per problemi di classificazione e ottimizzazione). Questa rete utilizza un algoritmo di apprendimento basato sulla retropropagazione degli errori e non sulla evoluzione verso stati energetici bassi. La applicazione del Simulated Annealing su questa rete è stata realizzata in via sperimentale con risultati soddisfacenti nella soluzione di diversi problemi; la filosofia di trasporto di questa teoria su questo tipo di rete (non potendosi basare su stati energetici) è stata quella di fornire i neuroni di una legge di attivazione a sigmoide variabile in funzione della temperatura: i neuroni si attivano (a parità di segnali di ingresso) maggiormente alle basse temperature(questo comporta anche una differente attività di modifica dei pesi delle connessioni sinaptiche da parte dell algoritmo di error_back_propagation alle diverse temperature).

ANALISI DEL CODICE C GENERATO

l Iistati 2 e 3 sono i files prova.c e prova.h generati da Neuronx, dopo un addestramento sul problema "giocattolo" del riconoscimento di profili altimetrici con cinque inputs.Il listato 2 contiene le procedure di esecuzione della rete e quelle di input /output e normalizzazione. Le procedure di fuzzificazione e defuzzificazione contengono solo un return perchè questa rete non ha interfacce fuzzy(defuzzy_in_flag=0 e fuzzy_out_flag=0 nei dati pubblici). Le procedure di normalizzazione e di denormalizzazione contengono il codice relativo perchè sono attivate dai flag normaliz_flag=1 e denormaliz_flag=1(dalla scala reale della variabile alla scala 0.0 - 1.0 e viceversa). Il listato 3 è il file prova.h (include in prova.c) che contiene le matrici w1,w2,w3 di valori float corrispondenti ai pesi sinaptici che connettono lo strato input con lo strato hidden1 di neuroni, lo strato hidden1 con lo strato hidden2 e lo strato hidden2 con lo strato di output. Questi valori corrispondono ai valori ottenuti dopo un addestramento con algoritmo a retropropagazione dell errore sul problema dei profili altimetrici. Tale addestramento è stato effettuato in regime termico dinamico, come dimostra la dichiarazione "float t=0.513044" nei dati pubblici: tale valore sarebbe uguale a 1 in caso contrario. Questo valore di temperatura è quello associato al momento in cui è stato fermato il processo di addestramento. Nel caso in cui vengano scelte caratteristiche differenti nel pretrattamento dei dati (come la normalizzazione quadratica)o l'interfacciamento con dati sfumati, il codice c avrà differenti valori nei flags definiti nei dati pubblici e saranno presenti le funzioni relative complete.



LISTATO 2

/* THIS PROGRAM IN C LANGUAGE IS A EBP NEURAL NET CREATED WITH NEURONX1 (NEURAL NETS C CODE GENERATOR) BY LUCA MARCHESE */ #include <stdio.h> #include <math.h> #include <prova.h> /*BUG: correggere in #include "prova.h"*/ #define maxline 100 int nx=5; int ny=5; int nh1=9; int nh2=9; float func_res; int normaliz_flag=1; int denormaliz_flag=1; int square=0; float offset=0.000000; float normak=100.000000; int defuzzy_in_flag=0; int fuzzy_out_flag=0; float t=0.513044; float x[100]; float h1[100]; float h2[100]; float y[100]; main() { if(input()) { exec(); output(); return 1; } return 0; } exec() { int k=0; int j=0; float a; while(k!=nh1) h1[k++]=0; /*hidden1 initalization = 0*/ h1[k]=1; /*bias*/ k=0; while(k!=nh2) h2[k++]=0; /*hidden2 initialization = 0*/ h2[k]=1; /*bias*/ k=0; while(k!=ny) y[k++]=0; /*output initialization = 0*/ x[nx]=1; /*input bias initialization*/ k=0; while(j!=nh1) /*h1 calculation*/ { k=0; a=0; /*any h1=0 initialization*/ while(k!=nx+1) a=a+(w1[j][k]*x[k++]); /*h1 activation calculation*/ f(a); h1[j++]=func_res; /*output calculation*/ } j=0; while(j!=nh2) /*h2 calculation*/ { k=0; a=0; /*any h1=0 initialization*/ while(k!=nh1+1) a=a+(w2[j][k]*h1[k++]); /*h2 activation calculation*/ f(a); h2[j++]=func_res; /*output calculation*/ } j=0; while(j!=ny) /*y calculation*/ { k=0; a=0; /*any y=0 initialization*/ while(k!=nh2+1) a=a+(w3[j][k]*h2[k++]); /*y activation calculation*/ f(a); y[j++]=func_res; /*output calculation*/ } return; } f(a) float a; { float b; b=1/(1+exp(-a/t)); func_res=b; return; } input() { char *file="prova.in"; FILE *fpin; int k=0; if(!(fpin=fopen(file,"r"))) { printf("ERROR OPENING INPUT FILE\n"); return 0; } if(!defuzzy_in_flag)while(k!=nx) fscanf(fpin,"%f",&x[k++]); x[k]=1; if((normaliz_flag)&&(!defuzzy_in_flag)) input_data_normalizer(); if((defuzzy_in_flag)&&(!normaliz_flag)) defuzzification_in(fpin); fclose(fpin); return 1; } output() { char *file="prova.out"; FILE *fpout; int k=0; if(!(fpout=fopen(file,"w"))) { printf("ERROR OPENING OUTPUT FILE\n"); return ; } if((fuzzy_out_flag)&&(!denormaliz_flag)) fuzzification_out(fpout); if((denormaliz_flag)&&(!fuzzy_out_flag)) output_data_denormalizer(); if(!fuzzy_out_flag)while(k!=ny) fprintf(fpout,"%f\n",y[k++]); fclose(fpout); return ; } input_data_normalizer() /*normalization to values v 0 < v < 1*/ { int k=0; while(k!=nx) x[k]=(x[k++]+offset)/normak; k=0; if(square) while(k!=nx); { x[k]=x[k]*x[k]; k++; } return; } output_data_denormalizer() { int k=0; if(square) while(k!=nx) y[k]=sqrt(y[k++]); while(k!=ny) y[k]=y[k++]*normak-offset; return; } fuzzification_out(fpout) FILE *fpout; { return; } defuzzification_in(fpin) FILE *fpin; { return; }


LISTATO 3

/*LEARNING_HEADER_FILE*/ float far w1[9][6]={3.248578,-0.168329,-4.854014,-0.148738,0.435997,1.908123, -2.819315,-1.173162,-3.325368,2.926156,7.184569,-1.274087,2.919860,2.775792, 6.331062,-2.334243,-8.806980,-0.069663,-6.937530,0.348315,2.925305,1.283903, 3.154221,1.400293,7.618520,0.423969,-3.707562,-1.197842,-2.593067,0.737628, 0.106994,0.145101,-0.007456,-0.039538,0.008107,0.094729,-0.098390,0.133408, 0.338889,-0.056152,0.173400,0.021692,0.019445,-0.286478,0.103537,0.111047, 0.314026,0.006780,-0.013501,0.176355,-0.021135,0.181239,0.006862,-0.105471, }; float far w2[9][10]={-2.077883,0.767727,-0.584588,3.150063,-3.833194,-0.389686, 0.229002,0.096596,0.114084,0.163734,-1.022036,3.448938,-5.098722,1.568256, -2.456146,0.526446,0.266967,0.595630,0.455010,0.131174,1.849635,-3.917503, 5.342775,-2.050846,4.432072,1.498487,0.475523,-0.349084,0.128589,-0.072857, -3.624948,-3.981793,7.178647,-2.805038,1.329446,-2.564022,0.162812,0.613991, 0.123508,0.177819,-3.550605,-2.135846,4.345431,4.950200,-3.462358,-1.334133, 0.587248,-0.124747,0.002104,0.181317,0.211475,0.871656,-0.030261,0.460907, 0.048518,1.088949,0.513699,0.319656,0.529848,-0.166475,-0.023568,0.813581, 0.321707,0.788963,-0.412579,-0.013629,-0.024483,-0.412023,0.575393,0.366901, -0.029459,0.582926,0.173883,-0.244128,0.175112,0.569956,0.577285,-0.222923, 0.170567,0.376047,0.019090,0.387615,0.012755,-0.027384,0.024187,0.404193, 0.007966,0.404439,0.404142,0.403559, }; float far w3[5][10]={0.716600,-2.232694,-0.664696,0.841474,7.530255,-5.672661, -0.214670,-0.129960,-0.109924,-0.072957,-3.450566,4.449509,1.359750,-2.661987, -7.623822,-2.760651,-0.088083,0.320317,0.132743,-0.177554,2.527434,4.761584, -7.463439,-2.054665,-1.135034,-1.482672,0.270768,-0.048533,0.245478,-0.065364, -1.509188,-8.215578,0.146611,4.062209,-3.707586,-2.923457,-0.348058,0.133766, 0.665961,0.090000,-1.948043,-2.391392,4.478242,-5.598677,2.806209,-2.877502, -0.256568,-0.355556,-0.072116,-0.164903, };



RETI NEURALI SU PERSONAL COMPUTER + FUZZY LOGIC
marchese@mbox.ulisse.it