|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Senior Member
Iscritto dal: Mar 2009
Messaggi: 753
|
[C] Problemi con rete neurale feedforward
Ciao ho un problema nell'addestramento di una semplice rete neurale del tipo in oggetto.
Il mio intento è eseguire una somma. Sono alle prime armi in questo campo. Sono riuscito a creare la struttura della rete composta dai 3 layer: input, nascosto e di output. Per l'apprendimento utilizzo l'algoritmo "Widrow*Hoff", un algoritmo di apprendimento supervisionato che calcola i pesi necessari partendo da pesi casuali, e apportando a questi delle modifiche progressive in modo da convergere alla soluzione finale. Il mio problema è che diverge alla grande ![]() nel senso che già dopo aver ciclato per due "epoche" ci si accorge subito che non stà funzionando. Il delta output e l'errore tendono all'infinito sin dal terzo ciclo di addestramento..... Di seguito inserisco il main che da un'idea sul programma in termini generali.... spero che qualcuno mi possa dare un mano.... nel caso posso allegare tutti i sorgenti se volete provarla direttamente. (ho il progetto codeblocks per Linux) Delle formule credo di esserne sicuro. (Come funzione di trasferimento ho utilizzato l'identità per semplicità) per l'addestramento uso un file di testo dove ho inserito sequenzialmente addendi più risultato per n volte... il main: Codice:
int main(int argc,const char**argv) { DEBUG = 0; int num; switch(argc) { case 2: { if(!strncmp(argv[1],"-d",2)) DEBUG = 1; break; } case 3: { if(!strncmp(argv[1],"-f",2)) { num = atoi(argv[2]); gen_file_t(num); return 0; } } case 1: break; default: { fprintf(stderr,"Warning! - too many arguments\n"); goto ERR; } } int fd; int i,j,x=0; int status; float temp, des_out, out_delta, net_output; neuralnet *net = init_net(); net->input_layer = new_layer(numb_neurons); net->hidden_layer = new_layer(numb_neurons); net->output_layer = new_layer(numb_neurons); // 16 neurons for each layer add_neurons(net->input_layer); add_neurons(net->hidden_layer); add_neurons(net->output_layer); // Link input layer to hidden layer and the hidden layer to output layer link_layers(net->input_layer,net->hidden_layer); link_layers(net->hidden_layer,net->output_layer); //Open training file fd = open_training_file(); if(fd<=0) { fprintf(stderr,"Fail to open %s, check it\n",TRAINING_FILE); free(net); return -1; } // loop for max_epochs time for(j = 0; j < net->max_epochs; j++) { // Read the two input do { x++; // And check if get_data() return a negative value if((status = get_data(&temp,fd)) < 0) { fprintf(stderr,"Invalid input data\n"); free(net); return -1; } // loop for every elements of input layer for(i = 0; i < net->input_layer->num_elements; i++) { // The post-synaptic potential value of neuron is just read from input, and the // transfer value will be equal because our transfer function is an identity net->input_layer->elements[i]->prop_value = (_PRECISION)temp; net->input_layer->elements[i]->trans_value = (_PRECISION)temp; } propagate_into_layer(net->hidden_layer); propagate_into_layer(net->output_layer); } while(x<2); x=0; // Get desired output if((status = get_data(&des_out,fd)) < 0) { fprintf(stderr,"Invalid input data\n"); free(net); return -1; } // Calculate variation of synaptic weights and update out_delta = compute_output_delta(net->output_layer->elements[0]->prop_value,des_out); // Dj = (Yj-dj)f'(Pj) update_output_weights(net->output_layer,out_delta,net->l_rate); // DWij = -nDjXi update_output_weights(net->hidden_layer,out_delta,net->l_rate); commit_weight_changes(net->output_layer); commit_weight_changes(net->hidden_layer); net_output = net->output_layer->elements[0]->prop_value; printf("DES=%f\tERROR=%f\tOUT=%f\tDELTA=%f\n",des_out,(des_out-net_output),net_output,out_delta); } close(fd); free(net); return 0; ERR: fprintf(stderr,"Usage: ./%s -d | -f <numb>\n" "'-d' for debug messages\n" "'-f' <numb> generate a training file, 'numb' is number of sums\n",argv[0]); return 1; } Codice:
matteo@Moon:~/ANNs/sum_ai/bin/Debug$ ./sum_ai -d DES=162.755081 ERROR=142.230316 OUT=20.524765 DELTA=-142.230316 DES=94.228630 ERROR=-184006353.771370 OUT=184006448.000000 DELTA=184006352.000000 DES=148.786011 ERROR=-267646241709250664464384.000000 OUT=267646241709250664464384.000000 DELTA=267646241709250664464384.000000 DES=51.351055 ERROR=inf OUT=-inf DELTA=-inf DES=47.134418 ERROR=inf OUT=-inf DELTA=-inf DES=72.565201 ERROR=-nan OUT=-nan DELTA=-nan DES=105.249115 ERROR=nan OUT=nan DELTA=nan DES=142.260590 ERROR=nan OUT=nan DELTA=nan DES=21.730181 ERROR=nan OUT=nan DELTA=nan DES=41.741848 ERROR=nan OUT=nan DELTA=nan DES=154.875870 ERROR=nan OUT=nan DELTA=nan DES=106.160805 ERROR=nan OUT=nan DELTA=nan ..... ![]() grazie per l'aiuto. ![]() |
![]() |
![]() |
![]() |
#2 |
Senior Member
Iscritto dal: Dec 2005
Città: Istanbul
Messaggi: 1817
|
E' difficile dire qualcosa di preciso dato che manca la parte piu' "succosa" del codice.
In ogni caso: * quanti sono i neuroni per i vari strati ? Immagino 2 di ingresso e uno di uscita, ma in mezzo ? * usa un solo elemento di training che e' piu' semplice capire il comportamento dell'algortimo. * fai una esecuzione in cui stampi a console tutti i pesi e i delta che hai calcolato; ho il dubbio che il problema sia proprio nel calcolo dei delta, visto che ottieni valori sballati dal primo passo.
__________________
One of the conclusions that we reached was that the "object" need not be a primitive notion in a programming language; one can build objects and their behaviour from little more than assignable value cells and good old lambda expressions. —Guy Steele |
![]() |
![]() |
![]() |
#3 | ||||
Senior Member
Iscritto dal: Mar 2009
Messaggi: 753
|
Quote:
Quote:
utilizzo 16 neuroni per ogni layer, sono 3 layer in totale. ma ho provato anche con uno.... il numero è definito da una variabile globale che vado a cambiare. essendo i neuroni (tra layer) interconnessi tutti con tutti, prendo l'uscita di uno di quelli nel layout di output Quote:
Quote:
è evidente, non riesco a capire dove sia il punto. Ho provato ad inserire un'asserzione ogni volta che un peso di una sinapsi viene aggiornato, ci sono ora un sacco di righe in più a video... ti posto quelle significative (credo), quando passa al ciclo successivo, o meglio credo che sia quando c'è la prpagazione al layout di output; il valore delta e peso assumono valori sicuramente sbagliati. Codice:
synapsi 15: weight: 7392.921875, delta: 7392.902832 synapsi 0: weight: -18187784191737856.000000, delta: -18187784191737856.000000 il file che uso per il training è costituito così nelle prime righe: Codice:
66.757889;95.997185;162.755074;85.691956;8.536676;94.228632;85.233665 |
||||
![]() |
![]() |
![]() |
#4 | |
Senior Member
Iscritto dal: Dec 2005
Città: Istanbul
Messaggi: 1817
|
Quote:
Che tipo di somma vuoi imparare ? Se ad esempio ti interessa la somma di due numeri (diciamo float), il metodo piu' semplice (o perlomeno che viene in mente a me), e' quello di utilizzare due neuroni nello strato di ingresso e uno di uscita. Ognuno dei due neuroni di ingresso riceve come segnale il valore da sommare, e il segnale di uscita dell'unico neurone del terzo strato ti da il risultato. Quindi quando parlo di un singolo elemento di training intendo tre valori numerici: la coppia di ingresso (e.g. 21 e -0.5) e il risultato (20.5). Stai procedendo differentemente ? Se si', come ?
__________________
One of the conclusions that we reached was that the "object" need not be a primitive notion in a programming language; one can build objects and their behaviour from little more than assignable value cells and good old lambda expressions. —Guy Steele |
|
![]() |
![]() |
![]() |
#5 |
Senior Member
Iscritto dal: Mar 2009
Messaggi: 753
|
si esatto la somma di due float.
E per il training, due addendi e il risultato, esattamente come hai detto. La rete però ha 16 neuroni per ogni layer. Non so se questo è un problema. Ma ragionando credo che vada bene se ne prendo uno per l'uscita. Probabilmente sbaglio a passargli gli input: - il primo valore (il primo addendo) lo passo a tutti i neuroni in input, - propago nel layer nascosto, poi propago sull'output - introduco il secondo addendo - ripropago nei due layer. - Solo a questo punto vado a calcolare il delta con il valore che trovo in output della rete e il terzo dato che acquisisco quindi faccio gli aggiornamenti, come si vede dal codice. |
![]() |
![]() |
![]() |
#6 | |
Senior Member
Iscritto dal: Dec 2005
Città: Istanbul
Messaggi: 1817
|
Quote:
![]() Non ha molto senso dare lo stesso input a piu' neuroni perche' vuol dire che svolgono lo stesso ruolo, e' una duplicazione inutile e dannosa che complica solo i conti e la funzione generata. Inoltre non capisco come calcoli il risultato. Propagando il valore del secondo addendo sovrascrivi tutti i valori generati dal primo, come "introduci" il secondo addendo ?
__________________
One of the conclusions that we reached was that the "object" need not be a primitive notion in a programming language; one can build objects and their behaviour from little more than assignable value cells and good old lambda expressions. —Guy Steele |
|
![]() |
![]() |
![]() |
#7 | |
Senior Member
Iscritto dal: Mar 2009
Messaggi: 753
|
Quote:
Faccio così, mantengo parte delle funzioni che dovrebbero essere corrette. Ristrutturo l'esempio utilizzando come hai detto due neuroni in input, uno in uscita. A una cosa, nel layer intermedio, quanti è bene inserirne? O lascio perdere e uso solo due layer per ora? A questo punto prova a rieseguire. Sbagliavo il principio. E' che la guida che mi ha introdotto a quanto pare è fatta con i piedi. ![]() mi accorgo che in molti punti è cannata. Anche le funzioni in C di esempio hanno errori vari che avevo corretto. |
|
![]() |
![]() |
![]() |
#8 |
Senior Member
Iscritto dal: Mar 2009
Messaggi: 753
|
ciao,
allora ho modificato l'esempio. Ho fatto in modo che il numero dei neuroni per ogni layer è deciso da variabili globali. Ho mantenuto 3 livelli. 2 neuroni in input, uno per addendo. 3 nel layer nascosto. 1 in quello di uscita. A questo punto purtroppo ho l'identico problema. Il procedimento che seguo è: - far leggere i due input ai due neuroni del primo strato. Un per uno. - Propago attraverso i layer. - Confronto il valore desiderato con l'ouput e aggiorno i pesi sinattici. - Stampo i risultati ripeto. A questo punto ci deve essere qualche altro errore... Il calcolo del delta è il seguente: Codice:
_PRECISION compute_output_delta(_PRECISION output_prop_value, _PRECISION des_out) { _PRECISION delta; // Dj = (Yj-dj)f'(Pj) delta = (output_prop_value - des_out) * linear_derivate(output_prop_value); return delta; } il risultato di linear_derivate() sarà sempre uno. Ma non penso sia questa funzione il problema... potenziale: Codice:
_PRECISION potential(neuron* nPtr) { _PRECISION aux_value = 0; int i=0; for(i=0;i<nPtr->num_in_links;i++) // The potential value is the summation of synapse weights multiplied with their transfer values aux_value += (nPtr->in_links[i]->weight * nPtr->in_links[i]->in->trans_value); return aux_value; } Codice:
matteo@Moon:~/ANNs/sum_ai/bin/Debug$ ./sum_ai -d DES=162.755081 ERROR=162.755081 OUT=0.000000 DELTA=-162.755081 DES=94.228630 ERROR=94.228630 OUT=0.000000 DELTA=-94.228630 DES=148.786011 ERROR=-99988507983723.218750 OUT=99988507983872.000000 DELTA=99988507983872.000000 DES=51.351055 ERROR=-41592171424451106627584687724390514688.000000 OUT=41592171424451106627584687724390514688.000000 DELTA=41592171424451106627584687724390514688.000000 DES=47.134418 ERROR=inf OUT=-inf DELTA=-inf DES=72.565201 ERROR=-nan OUT=-nan DELTA=-nan ![]() |
![]() |
![]() |
![]() |
#9 | |
Senior Member
Iscritto dal: Mar 2009
Messaggi: 753
|
Quote:
|
|
![]() |
![]() |
![]() |
#10 |
Senior Member
Iscritto dal: Apr 2003
Messaggi: 591
|
|
![]() |
![]() |
![]() |
#11 |
Senior Member
Iscritto dal: Mar 2009
Messaggi: 753
|
grazie,
è esatto. Ho capito che l'aggiornamento dei pesi fatto in quel modo, non supporta più di 2 layer. Questo perchè è impossibile determinare l'errore per i neuroni sul layer nascosto essendo appunto intermedio. (ERRORE = Ydesideato - Yrete) Infatti utilizzando due neuroni in input e uno per l'ouput sembra ok. Ho ancora una perplessità. Se utilizzo come training per la somma valori tra 0 e 100 non funziona correttamente. Ho l'errore che permane molto alto. So che le reti non sono certo usate per le somme, ma voglio capire se sbaglio io qualcosa oppure c'è un'altra ragione...... Cmq se utilizzo input tra 0 e 1 lavora correttamente. La funzione di trasf. che ho usato è la saturazione lineare, quindi restituisce valori tra 0 e 1, in accordo con il peso... non capisco perchè su una guida c'era indicata l'identità....... Datemi un parere sull'ouput: (e se quello che sto dicendo è corretto) Codice:
matteo@Moon:~/ANNs/sum_ai/bin/Debug$ ./sum_ai DES=0.691885 ERROR=0.367688 OUT=0.324197 DELTA=0.367688 DES=1.784865 ERROR=0.831504 OUT=0.953361 DELTA=0.831504 DES=1.125133 ERROR=0.126342 OUT=0.998791 DELTA=0.126342 DES=0.171665 ERROR=0.008836 OUT=0.162829 DELTA=0.008836 DES=0.531222 ERROR=0.048165 OUT=0.483057 DELTA=0.048165 DES=1.563073 ERROR=0.094668 OUT=1.468405 DELTA=0.094668 DES=1.521969 ERROR=0.042583 OUT=1.479386 DELTA=0.042583 DES=1.446336 ERROR=-0.009548 OUT=1.455884 DELTA=-0.009548 DES=1.141066 ERROR=0.015600 OUT=1.125466 DELTA=0.015600 DES=0.504797 ERROR=-0.009949 OUT=0.514746 DELTA=-0.009949 DES=0.349549 ERROR=0.005565 OUT=0.343984 DELTA=0.005565 DES=1.641087 ERROR=-0.003137 OUT=1.644224 DELTA=-0.003137 DES=0.577347 ERROR=-0.009224 OUT=0.586571 DELTA=-0.009224 DES=1.534388 ERROR=0.001723 OUT=1.532665 DELTA=0.001723 DES=1.645598 ERROR=-0.000407 OUT=1.646005 DELTA=-0.000407 DES=0.789530 ERROR=0.003343 OUT=0.786187 DELTA=0.003343 DES=1.267519 ERROR=-0.011191 OUT=1.278710 DELTA=-0.011191 DES=0.560583 ERROR=0.005589 OUT=0.554994 DELTA=0.005589 DES=0.402530 ERROR=0.008367 OUT=0.394163 DELTA=0.008367 DES=0.545942 ERROR=-0.002994 OUT=0.548936 DELTA=-0.002994 DES=0.839283 ERROR=-0.011968 OUT=0.851251 DELTA=-0.011968 DES=0.362268 ERROR=0.007815 OUT=0.354453 DELTA=0.007815 DES=1.021461 ERROR=0.024671 OUT=0.996790 DELTA=0.024671 DES=1.279987 ERROR=-0.005000 OUT=1.284986 DELTA=-0.005000 DES=0.998938 ERROR=-0.003917 OUT=1.002855 DELTA=-0.003917 DES=1.305514 ERROR=0.007587 OUT=1.297927 DELTA=0.007587 DES=0.971595 ERROR=-0.001120 OUT=0.972715 DELTA=-0.001120 DES=0.569764 ERROR=-0.005455 OUT=0.575219 DELTA=-0.005455 DES=0.875260 ERROR=-0.000212 OUT=0.875472 DELTA=-0.000212 DES=1.168121 ERROR=-0.001626 OUT=1.169747 DELTA=-0.001626 DES=0.196045 ERROR=0.000688 OUT=0.195357 DELTA=0.000688 DES=0.858341 ERROR=-0.007866 OUT=0.866207 DELTA=-0.007866 DES=0.532047 ERROR=-0.001696 OUT=0.533743 DELTA=-0.001696 DES=0.856216 ERROR=0.005069 OUT=0.851147 DELTA=0.005069 DES=1.151172 ERROR=0.006237 OUT=1.144935 DELTA=0.006237 DES=0.868329 ERROR=-0.003296 OUT=0.871625 DELTA=-0.003296 DES=1.511173 ERROR=0.002040 OUT=1.509133 DELTA=0.002040 DES=1.351708 ERROR=0.004169 OUT=1.347539 DELTA=0.004169 DES=1.039200 ERROR=-0.003276 OUT=1.042476 DELTA=-0.003276 DES=0.695161 ERROR=0.001313 OUT=0.693848 DELTA=0.001313 DES=1.416479 ERROR=0.001566 OUT=1.414913 DELTA=0.001566 DES=0.386624 ERROR=-0.000414 OUT=0.387038 DELTA=-0.000414 DES=0.947277 ERROR=0.003804 OUT=0.943473 DELTA=0.003804 DES=0.937016 ERROR=0.002491 OUT=0.934525 DELTA=0.002491 DES=1.060540 ERROR=0.004055 OUT=1.056485 DELTA=0.004055 DES=0.343396 ERROR=-0.000738 OUT=0.344134 DELTA=-0.000738 DES=1.062788 ERROR=0.002792 OUT=1.059996 DELTA=0.002792 DES=0.720148 ERROR=-0.000827 OUT=0.720975 DELTA=-0.000827 DES=0.620662 ERROR=0.000488 OUT=0.620174 DELTA=0.000488 DES=0.529412 ERROR=0.000717 OUT=0.528695 DELTA=0.000717 DES=0.978521 ERROR=-0.001175 OUT=0.979696 DELTA=-0.001175 DES=0.762289 ERROR=-0.006032 OUT=0.768321 DELTA=-0.006032 DES=0.628338 ERROR=-0.002359 OUT=0.630697 DELTA=-0.002359 DES=1.022328 ERROR=-0.005409 OUT=1.027737 DELTA=-0.005409 DES=0.745693 ERROR=-0.001541 OUT=0.747234 DELTA=-0.001541 DES=0.705675 ERROR=-0.001219 OUT=0.706894 DELTA=-0.001219 DES=1.718164 ERROR=-0.000602 OUT=1.718766 DELTA=-0.000602 DES=0.550246 ERROR=-0.000311 OUT=0.550557 DELTA=-0.000311 DES=1.048688 ERROR=0.000764 OUT=1.047924 DELTA=0.000764 DES=1.487978 ERROR=-0.000728 OUT=1.488706 DELTA=-0.000728 DES=0.592400 ERROR=-0.001159 OUT=0.593559 DELTA=-0.001159 DES=1.365812 ERROR=0.000378 OUT=1.365434 DELTA=0.000378 DES=1.033112 ERROR=0.003239 OUT=1.029873 DELTA=0.003239 DES=0.250023 ERROR=-0.000023 OUT=0.250046 DELTA=-0.000023 Ultima modifica di Teo@Unix : 16-08-2010 alle 21:14. |
![]() |
![]() |
![]() |
#12 | ||
Senior Member
Iscritto dal: Dec 2005
Città: Istanbul
Messaggi: 1817
|
Quote:
http://en.wikipedia.org/wiki/Backpropagation Quote:
__________________
One of the conclusions that we reached was that the "object" need not be a primitive notion in a programming language; one can build objects and their behaviour from little more than assignable value cells and good old lambda expressions. —Guy Steele |
||
![]() |
![]() |
![]() |
#13 | ||
Senior Member
Iscritto dal: Mar 2009
Messaggi: 753
|
Quote:
Quote:
Se io usassi una lineare f(x)=x non avrei poi ouput enormi? Quando calcolo il delta Codice:
// DWij = n*Dj*Xi sPtr->delta = sPtr->in->trans_value*delta*l_rate; di conseguenza quando aggiorno i pesi: Codice:
for(j=0; j < nPtr->num_in_links; j++) { sPtr = nPtr->in_links[j]; sPtr->weight += sPtr->delta; // Increase or reduce weight (Hebb) sPtr->delta = 0; // Reset delta } Praticamente è il problema cha avevo prima. Dove è sbagliato il mio ragionamento? So che sono domande banali, ma sono esattamente all'inizio. Grazie. Ultima modifica di Teo@Unix : 17-08-2010 alle 16:47. |
||
![]() |
![]() |
![]() |
#14 | |
Senior Member
Iscritto dal: Nov 2002
Messaggi: 6066
|
Quote:
http://www.faqs.org/faqs/ai-faq/neur...section-6.html che è una piccola aggiunta alla backpropagation per evitare pesi grandi. Ultima modifica di Unrue : 17-08-2010 alle 20:17. |
|
![]() |
![]() |
![]() |
#15 | |
Senior Member
Iscritto dal: Mar 2009
Messaggi: 753
|
Quote:
ma non sto utilizzando backpropagation. Praticamente stò utilizzando un percettrone. Semplicemente mi chiedo come procedere se voglio addestrare la rete per eseguire una somma ma con input più grandi, non tanto perchè mi interessa la somma..... era solo per concludere l'esempio che avevo fatto. |
|
![]() |
![]() |
![]() |
#16 | |
Senior Member
Iscritto dal: Nov 2002
Messaggi: 6066
|
Quote:
|
|
![]() |
![]() |
![]() |
#17 |
Senior Member
Iscritto dal: Mar 2009
Messaggi: 753
|
credo di aver capito.
Ora vedrò di guardarmi la backpropagation. Senza normalizzare nulla l'esempio funziona bene con valori tra 0 e 1. Grazie a tutti. |
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 09:18.