miei programmi in c su knoppix e relativi problemi

fabio93

Utente Attivo
609
173
CPU
AMD Ryzen 5 2400G
Dissipatore
Arctic Alpine64 Plus
Scheda Madre
Gigabyte GA-AX370-Gaming 3
HDD
Crucial MX500 250 GB, Crucial BX500 240 GB
RAM
G.Skill F4-3200C14D-16GFX FlareX 16 GB
Monitor
HP 2010i
PSU
Corsair TX550M
Case
Sharkoon M25-W
Periferiche
Magicforce 68, Logitech G203
OS
Windows 10 Pro, Fedora 31
C:
if (o_synapse[ i ].dEdw * (o_neuron[ i ].dEdy* d_sigmoid ( o_neuron[ i ].value ) * h_neuron[ j ].value)  > 0)
{//apro3
    {//apro 4
    delta_w = - etapiu * o_neuron[ i ].dEdy * d_sigmoid ( o_neuron[ i ].value ) * h_neuron[ j ].value;
    o_synapse[i * ( 3 + 1 ) + j ].weight += delta_w;
    }//chiudo 4

    delta_w = - etapiu * o_neuron[ i ].dEdy * d_sigmoid ( o_neuron[ i ].value );
    o_synapse[i * ( 3 + 1 ) + j ].weight += delta_w;
}//chiudo3
A che servono le parentesi 4? Non delimitano il corpo di un if, ma costituiscono un cosiddetto blocco in-line, che in questo caso non serve (di solito si usano per dichiarare una variabile visibile solo al loro interno, ma non è questo il caso).
 

anche_per_il_direttore

Nuovo Utente
63
2
le parentesi 4 avrebbero avuo lo scopo di isolare il for i dal for j, se guardi il primo pezzo di codice del messaggio precedente quando il ciclo j finisce prima di iniziare il nuovo ciclo i c'e' un'istruzione che cattura un valore con il valore j che causa l uscita dal ciclo, l idea e' che vorrei riprodurre lo stesso effetto dentro un ciclo if, ecco perche' ho messo le parentesi 4 ma come dicevo prima non sono sicuro che funzioni il modo in cui l ho scritto
 

fabio93

Utente Attivo
609
173
CPU
AMD Ryzen 5 2400G
Dissipatore
Arctic Alpine64 Plus
Scheda Madre
Gigabyte GA-AX370-Gaming 3
HDD
Crucial MX500 250 GB, Crucial BX500 240 GB
RAM
G.Skill F4-3200C14D-16GFX FlareX 16 GB
Monitor
HP 2010i
PSU
Corsair TX550M
Case
Sharkoon M25-W
Periferiche
Magicforce 68, Logitech G203
OS
Windows 10 Pro, Fedora 31
Un costrutto if non è un ciclo, quindi quelle parentesi così non servono.
 

anche_per_il_direttore

Nuovo Utente
63
2
salve a tutti, credo di aver sistemato il problema con le if, e ho inserito nel codice altre tre semplici funzioni di massimo, minimo e segno, il codice pero' non compila, credo sia un problema di come ho dichiarato le variabili, aiuti sempre ben accetti, posto inoltre per chi fosse interessato un secondo codice aggiornato relativo ad una rete neurale con algoritmo di apprendimento backpropagation funzionante (la dimensione della rete neurale puo' essere modificata all interno del codice stesso, per controllare che effettivamente gli errori dei neuroni e i relativi delta subissero effettivamente una modifica al variare degli ingressi ho posizionato all interno del codice dei printf e limitato le epoche di apprendimento, qualora si decidesse di utilizzare la rete neurale per testare funzioni note (cosa che ancora non ho fatto) si ricordi di oscurare le printf inserite altrimenti supponendo di inserire 50000 epoche nel codice diventerebbe molto complicato gestire tutte le stampe a video)
ecco il primo codice (rete neurale con RPRO e messaggi di errore)
C:
/*rete di tre layers; layer 1 con 2 neuroni; layer 2 con 3 (ne ho provati 200) neuroni; layer 3 con 1 neurone*/

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>

// Precisione dei valori
typedef double T_Precision;


// Struttura di un neurone
struct Neuron
{
 T_Precision value;// Uscita del percettrone
 T_Precision dEdy;//Errore del neurone
};
//struct Neuron *i_neuron, *h_neuron, *o_neuron;//variabili di tipo Neuron


// Struttura di una connessione tra due neuroni (sinapsi)
struct Synapse
{
 T_Precision weight; // Peso della connessione
 T_Precision dEdw;//Errore della connessione
};
//struct Synapse *h_synapse, *o_synapse;//variabili di tipo Synapse




//DICHIARAZIONE FUNZIONI

void max ( double T_Precision r,  double T_Precision z);//dichiarazione funzione massimo tra due valori

void min ( double T_Precision r,  double T_Precision z);//dichiarazione funzione minimo tra due valori

int sign (float x);//dichiarazione funzione segno

float sigmoid(float x);//dichiarazione funzione sigmoide

float d_sigmoid(float x);//dichiarazione funzione derivata della sigmoide

void run_network( struct Neuron *i_neuron, size_t input_size,    //dichiarazione funzione che fa operare la rete di 3 strati,calcola le uscite di
struct Neuron *h_neuron, struct Synapse *h_synapse, size_t hidden_size, //ogni strato, un percettrone alla volta, fino a determinare le uscite
struct Neuron *o_neuron, struct Synapse *o_synapse, size_t output_size );//della rete

void init_weight( struct Synapse *synapse, size_t layer_size, size_t prev_layer_size );//dichiarazione funzione inizializzazione pesi


void init_dEdw( struct Synapse *synapse, size_t layer_size, size_t prev_layer_size );//dichiarazione funzione inizializzazione dEdw


void resilient_backpropagation( struct Neuron *i_neuron, size_t input_size,
struct Neuron *h_neuron, struct Synapse *h_synapse, size_t hidden_size,
struct Neuron *o_neuron, struct Synapse *o_synapse, size_t output_size,
const T_Precision *dx, const T_Precision *dy, size_t sn,
const T_Precision etapiu, const T_Precision etameno, const T_Precision desired_error );//dichiarazione funzione di retropropagazione dell'errore

//FINE DICHIARAZIONI FUNZIONI
 
 
 
 int main(void)
 
{
    // Inizializzo il generatore di numeri pseudocasuali
    srand( (size_t) time( NULL ) );
 
    // Dimensioni della rete
    const size_t input_size = 2;
    const size_t hidden_size = 3;
    const size_t output_size = 1;
 
    // Creo i neuroni degli strati
    struct Neuron i_neuron[ input_size ];
    struct Neuron h_neuron[ hidden_size];
    struct Neuron o_neuron[ output_size];
 
    // Creo le sinapsi degli strati (+ quella del bias)
    struct Synapse h_synapse[ (input_size + 1) * (hidden_size) ];
    struct Synapse o_synapse[ (hidden_size + 1) * (output_size) ];
    
    
    // Iteratore
    size_t i, j;
 
    // Numero di esempi dell'insieme di addestramento
    const size_t sn = 4;
 
    // Preparo l'insieme di addestramento per l'operatore XOR//---sn*input_size
    const T_Precision dx[] = { 0,0, 0,1, 1,0, 1,1 };
                        
    const T_Precision dy[] = { 0, 1, 1, 0 };//valori desiderati--- sn*output_size
 
    const T_Precision etapiu = 1.2; 
    const T_Precision etameno = 0.5;
    
    // Tasso di apprendimento
    //const T_Precision eta = 0.5;
    
    // Errore desiderato
    const T_Precision desired_error = 0.0001;
 
    // Addestro la rete neurale
    resilient_backpropagation(i_neuron, input_size,
    h_neuron, h_synapse, hidden_size,
    o_neuron, o_synapse, output_size,
    dx, dy, sn, etapiu, etameno, desired_error );
 
    
    // Stampo l'intestazione della tabella
    printf( "[x1]\t[x2]\t[y]\n" );
 
    // Provo tutte le combinazioni degli ingressi
    for ( j = 0; j <= 1; j++ )
    {
        for ( i = 0; i <= 1; i++ )
        {
 
        // Imposto gli ingressi
        i_neuron[0].value = i;
        i_neuron[1].value = j;
 
        // Eseguo la rete neurale
        run_network( i_neuron, input_size,
        h_neuron, h_synapse, hidden_size,
        o_neuron, o_synapse, output_size );
 
        // Stampo gli ingressi e la rispettiva uscita
        printf( "%.0f\t%.0f\t%.0f\n", i_neuron[0].value, i_neuron[1].value, o_neuron[0].value );
        
        }
    }
 
 return 0;
 
}



void max ( double T_Precision r, double T_Precision z) //definizione funzione massimo
{
     double T_Precision mx;
     double T_Precision r;
     double T_Precision z;
    
     if (x >= y)
        
           mx = r;
     else
          mx = z;       
}



void min ( double T_Precision r, double  T_Precision z)//definizione funzione minimo
{
     double T_Precision mi;
     double T_Precision r;
     double T_Precision z;
    
     if (r < z)
        
           mi = r;
     else
          mi = z;       
}


int sign (float x)//definizione funzione segno
{
      int sg;
      
      if (x < 0)
      {
        sg = -1;
      }
      else if  x == 0)
      {
           sg = 0;
      }
      else
      {
       sg = 1;
      }
      return sg;
}
            



float sigmoid(float x)//definizione funzione sigmoide
{
     float exp_value;
     float return_value;

     /*** Exponential calculation ***/
     exp_value = exp((double) -x);

     /*** Final sigmoid value ***/
     return_value = 1 / (1 + exp_value);

     return return_value;
}




float d_sigmoid(float x)//definizione funzione derivata della sigmoide
{
     float exp_value;
     float return_value;

     /*** Exponential calculation ***/
     exp_value = exp((double) -x);

     /*** Final sigmoid value ***/
     return_value = (1 / (1 + exp_value))*(1-(1 / (1 + exp_value)));


     return return_value;
}




void run_network(struct Neuron *i_neuron, size_t input_size,    //definizione della funzione che fa operare la rete di 3 strati,calcola le uscite di
struct Neuron *h_neuron,struct Synapse *h_synapse, size_t hidden_size, //ogni strato, un percettrone alla volta, fino a determinare le uscite
struct Neuron *o_neuron, struct Synapse *o_synapse, size_t output_size )//della rete

{

 // Potenziale di attivazione
 float potential;
 // Iteratori
 size_t j, i;

    // Calcolo le uscite dello strato intermedio hidden
    for ( i = 0; i < hidden_size; i++ )
 
        {
            // Azzero il potenziale di attivazione
            potential = 0;
                // Calcolo il potenziale di attivazione
                    for ( j = 0; j < input_size; j++ )
                    {
                        potential += i_neuron[j].value * h_synapse[i * ( input_size + 1 ) + j].weight;
                    }
            // Aggiungo il valore del bias
            potential += h_synapse[i * ( input_size + 1 ) + j].weight;
 
            // Calcolo l'uscita del neurone sulla base del potenziale di attivazione
            h_neuron[i].value = sigmoid( potential ); //uscita del generico neurone nello strato hidden
        }
 
 
 
    // Calcolo le uscite dello strato di uscita
    for ( i = 0; i < output_size; i++ )
        
        {
            // Azzero il potenziale di attivazione
            potential = 0;
                // Calcolo il potenziale di attivazione
                    for ( j = 0; j < hidden_size; j++ )
                    {
                        potential += h_neuron[j].value * o_synapse[i * ( hidden_size + 1 ) + j].weight;
                    }
 
            // Aggiungo il valore del bias
            potential += o_synapse[i * ( hidden_size + 1 ) + j].weight;
 
            // Calcolo l'uscita del neurone sulla base del potenziale di attivazione
            o_neuron[i].value = sigmoid( potential );//uscita del neurone output
        }
}//fine funzione (procedura) run_network






void init_weight( struct Synapse *synapse, size_t layer_size, size_t prev_layer_size )//definizione funzione inizializzazione pesi
{
    // Valore casuale
    T_Precision random_;
    
    // Iteratori
    size_t j, i = 0;
 
    // Inizializzo i pesi sinaptici con dei valori casuali (inizializzo anche il peso del  bias)
    for (i=0 ; i < layer_size; i++ )
    {
        for ( j = 0; j <= prev_layer_size; j++ )
        {
            // Prelevo un valore casuale
            random_ = rand();
            // Imposto il valore del peso tra 0 e 1
            synapse[i * (prev_layer_size + 1) + j].weight = ( sin(random_) * sin(random_));//col seno al quadrato
                                                 //ho valori tra zero e uno
        }
    }
}//fine definizione funzione inizializzazione pesi
 
 
 
 
void init_dEdw( struct Synapse *synapse, size_t layer_size, size_t prev_layer_size )//definizione funzione inizializzazione dEdw
{
    // Valore casuale
    T_Precision random_;
    
    // Iteratori
    size_t  j, i = 0;
 
    // Inizializzo i pesi sinaptici con dei valori casuali (inizializzo anche il peso del  bias)
    for (i=0 ; i < layer_size; i++ )
    {
        for ( j = 0; j <= prev_layer_size; j++ )
        {
            // Imposto il valore del peso tra 0 e 1
            synapse[i * (prev_layer_size + 1) + j].dEdw = 0.1;//col seno al quadrato
                                         //ho valori tra zero e uno
        }
    }
}//fine definizione funzione inizializzazione dEdw



void resilient_backpropagation(struct Neuron *i_neuron, size_t input_size,
struct Neuron *h_neuron, struct Synapse *h_synapse, size_t hidden_size,
struct Neuron *o_neuron, struct Synapse *o_synapse, size_t output_size,
const T_Precision *dx, const T_Precision *dy, size_t sn,
const T_Precision eta_piu, const T_Precision eta_meno , const T_Precision desired_error )//definizione funzione di retropropagazione dell'errore
 
{
     // Errore della rete
    T_Precision error;
 
    // Modifica del peso sinaptico
    T_Precision delta_w;
    
    
    // Modifica del peso sinaptico
    T_Precision delta_ij;
    
    
    //valore delta minimo
    const T_Precision delta_min = 0.1;//exp(-6);
                            
    //valore delta massimo
    const T_Precision delta_max = 50;
                            
                            
    // Contatore delle epoche
    size_t epochs = 0;
 
    // Iteratori
    size_t  i,j,t;//ho aggiunto k per ciclare dentro le if
 
    // tasso di apprendimento positivo
    const T_Precision etapiu = 1.2;
    
    // tasso di apprendimento negativo
    const T_Precision etameno = 0.5;
 
    // Log di lavoro
    printf( "Inizio l'addestramento (etapiu = %.2f,etameno = %.2f, errore desiderato = %f).\n\n", etapiu, etameno, desired_error );
    
    
    
    // Inizializzo e stampo per ogni neurone i pesi sinaptici con dei valori casuali
    init_weight( h_synapse, hidden_size, input_size ); //inizializzazione peso neuroni dello strato nascosto
    init_weight( o_synapse, output_size, hidden_size );//inizializzazione peso neuroni dello strato output
    
    printf("pesi inizializzati dei neuroni intermedi\n\n");
    for (i=0 ; i < hidden_size; i++ )
    {
        for ( j = 0; j <= input_size; j++ )
        {

                    printf( "pesi_ o_syn=%f\n", h_synapse[i*(input_size+1)+j].weight );
                }
        }
        
    
    printf("\n");
    printf("pesi inizializzati dei neuroni in uscita\n\n");
    for (i=0 ; i < output_size; i++ )
    {
        for ( j = 0; j <= hidden_size; j++ )
        {
                     printf( "pesi_ o_syn=%f\n", o_synapse[i*(hidden_size+1)+j].weight );
                }
        }
        
    
    
    
    //inizializzo e stampo per ogni neurone i dEdw
    init_dEdw( h_synapse, hidden_size, input_size ); //inizializzazione dEdw peso neuroni dello strato nascosto
    init_dEdw( o_synapse, output_size, hidden_size );//inizializzazione dEdw peso neuroni dello strato output
 
    printf("\n");
    printf("valori dEdw inizializzati dei neuroni intermedi\n\n");
    for (i=0 ; i < hidden_size; i++ )
    {
        for ( j = 0; j <= input_size; j++ )
        {
                      printf( "dEdw_ o_syn=%f\n", h_synapse[i*(input_size+1)+j].dEdw );
                }
        }
        
    printf("\n");
    printf("valori dEdw inizializzati dei neuroni in uscita\n\n");
    for (i=0 ; i < output_size; i++ )
    {
        for ( j = 0; j <= hidden_size; j++ )
        {
                      printf( "dEdw_ o_syn=%f\n",o_synapse[i*(hidden_size+1)+j].dEdw );
                }
        }
    
    
    // Continuo l'addestramento finché non raggiungo
    // l'errore desiderato (max 50000 epoche)
    do
    {
    // Azzero l'errore della rete (somma degli errori della rete)
    error = 0.0;
    
    // Ripeto per tutti gli esempi nell'insieme di addestramento
    for ( t = 0; t < sn; t++ )
    {       //primo for
        
            // Prendo gli ingressi dall'esempio
            for ( i = 0; i < input_size; i++ )
            
            {
                i_neuron[i].value = dx[t * input_size + i];
            }
 
            // Eseguo la rete neurale
            run_network( i_neuron, input_size,
            h_neuron, h_synapse, hidden_size,
            o_neuron, o_synapse, output_size );
 
             // CALCOLO ERRORI DEGLI STRATI
        // Calcolo l'errore dello strato di uscita (in questo caso un neurone)
        for ( i = 0; i < output_size; i++ )
        {
        
            // Calcolo l'errore dell'uscita del neurone dE/dy_i = -(D_i - Y_i)
            o_neuron[i].dEdy = -( dy[t * output_size + i] - o_neuron[i].value );
 
            // Aggiungo l'errore al totale
            error += (( o_neuron[i].dEdy )*( o_neuron[i].dEdy)) ;
        }
 
 
         // Calcolo l'errore dello strato intermedio
        for ( i = 0; i < hidden_size; i++ )
            {
            
            // Azzero l'errore dei neuroni dello strato intermedio hidden
            h_neuron[i].dEdy = 0;
            
            // Calcolo l'errore dello strato intermedio dE/dz_k = SUM( dE/dy_j * dy_j/dP_j * dP_j/dz_k )
            for ( j = 0; j < output_size; j++ )
                {
                
                // Calcolo l'errore dell'uscita dei neuroni dello strato intermedio
                h_neuron[i].dEdy += o_neuron[j].dEdy *
                d_sigmoid ( o_neuron[j].value ) * o_synapse[j * ( hidden_size + 1 ) + i].weight;
                }
 
            // Calcolo l'errore dell'uscita del bias
            h_neuron[i].dEdy += o_neuron[j].dEdy *
            d_sigmoid ( o_neuron[j].value ) * o_synapse[j * ( hidden_size + 1 ) + i].weight;
            }
                 //FINE CALCOLO ERRORI DEGLI STRATI
 
 
 
                 //INIZIO AGGIORNAMENTO PESI DEI VARI STRATI
            // Aggiusto i pesi dello strato di uscita
            
                if     (o_synapse[i].dEdw * (o_neuron[i].dEdy*
            d_sigmoid ( o_neuron[i].value ) * h_neuron[j].value)  > 0)  {
            
            
        for ( i = 0; i < output_size; i++ )
    {
             // Correggo il peso sinaptico
            for ( j = 0; j < hidden_size; j++ )
        {
 
                                    
                delta_ij = min( (o_synapse[i].dEdw)*etapiu , delta_max);
                
                
                delta_w = -sign (o_neuron[i].dEdy *
            d_sigmoid ( o_neuron[i].value ) * h_neuron[j].value) * delta_ij;
 
                
 
            // Applico la modifica al peso sinaptico w = w + delta_w dei neuroni in uscita (uno in questo caso)
            o_synapse[i * ( hidden_size + 1 ) + j].weight += delta_w;//nuovi pesi strato uscita
            }
            // Calcolo la modifica del peso del bias delta_w = - eta * dE/dy_j * dy_j/dP_j * dP_j/dw_jk
            
              
                delta_w = -sign (o_neuron[i].dEdy *
            d_sigmoid ( o_neuron[i].value ) ) * delta_ij;
 
            
            // Aggiungo la correzione del bias w = w + delta_w
            o_synapse[i * ( hidden_size + 1 ) + j].weight += delta_w;//nuovo peso bias strato di uscita
                                                  
    }
                                                                                  }
            
            
            else if (o_synapse[i].dEdw * (o_neuron[i].dEdy *
            d_sigmoid ( o_neuron[i].value ) * h_neuron[j].value)  < 0)    {
            
                
        for ( i = 0; i < output_size; i++ )
    {
             // Correggo il peso sinaptico
            for ( j = 0; j < hidden_size; j++ )
        {
 
            
            delta_ij = max( (o_synapse[i].dEdw)*etameno , delta_min);
            
            
            
                delta_w = (o_neuron[i].dEdy *
            d_sigmoid ( o_neuron[i].value ) * h_neuron[j].value) - (o_synapse[i].dEdw);
            
            // Applico la modifica al peso sinaptico w = w + delta_w dei neuroni in uscita (uno in questo caso)
            o_synapse[i * ( hidden_size + 1 ) + j].weight += delta_w;
            
            
            (o_neuron[i].dEdy *
            d_sigmoid ( o_neuron[i].value ) * h_neuron[j].value) = 0;
            
            
        }
            // Calcolo la modifica del peso del bias delta_w = - eta * dE/dy_j * dy_j/dP_j * dP_j/dw_jk
            delta_w = (o_neuron[i].dEdy *
            d_sigmoid ( o_neuron[i].value )) - (o_synapse[i].dEdw);
            
            // Aggiungo la correzione del bias w = w + delta_w
            o_synapse[i * ( hidden_size + 1 ) + j].weight += delta_w;
            
            (o_neuron[i].dEdy *
            d_sigmoid ( o_neuron[i].value )) = 0;
            
            
    }
                                                                                   }
    
    
    
            else if  (o_synapse[i].dEdw * (o_neuron[i].dEdy *
            d_sigmoid ( o_neuron[i].value ) * h_neuron[j].value) == 0)    {
            
            
        for ( i = 0; i < output_size; i++ )
    {
             // Correggo il peso sinaptico
            for ( j = 0; j < hidden_size; j++ )
            
            
            {
            delta_w = -sign(o_neuron[i].dEdy *
            d_sigmoid ( o_neuron[i].value ) * h_neuron[j].value) * delta_ij;
 
            // Applico la modifica al peso sinaptico w = w + delta_w dei neuroni in uscita (uno in questo caso)
            o_synapse[i * ( hidden_size + 1 ) + j].weight += delta_w;
            }
                        
                        // Calcolo la modifica del peso del bias delta_w = - eta * dE/dy_j * dy_j/dP_j * dP_j/dw_jk
            delta_w = -sign(o_neuron[i].dEdy *
            d_sigmoid ( o_neuron[i].value ) ) * delta_ij;
            
            // Aggiungo la correzione del bias w = w + delta_w
            o_synapse[i * ( hidden_size + 1 ) + j].weight += delta_w;
            
    }
            
                                              }
                                              
    
         
        
        
        //aggiusto i pesi dello strato nascosto
                            if     (h_synapse[i].dEdw * (h_neuron[i].dEdy *
            d_sigmoid ( h_neuron[i].value ) * i_neuron[j].value) > 0)      {

           for ( i = 0; i < hidden_size; i++ )
        {
             // Correggo il peso sinaptico
            for ( j = 0; j < input_size; j++ )
            {
            
                        
                delta_ij = min( (h_synapse[i].dEdw)*etapiu , delta_max);
                
                
                delta_w = -sign (h_neuron[i].dEdy *
            d_sigmoid ( h_neuron[i].value ) * i_neuron[j].value) * delta_ij;
 
                
            
            // Applico la modifica al peso sinaptico w = w + delta_w dei neuroni nascosti
            h_synapse[i * ( input_size + 1 ) + j].weight += delta_w;//nuovi pesi strato nascosto
            }
            
            
            
            // Calcolo la modifica del peso del bias delta_w = - eta * dE/dy_j * dy_j/dP_j * dP_j/dw_jk
            
                
                delta_w = -sign (h_neuron[i].dEdy *
            d_sigmoid ( h_neuron[i].value ) * delta_ij;
 
            
            // Aggiungo la correzione del bias w = w + delta_w
            h_synapse[i * ( input_size + 1 ) + j].weight += delta_w;//nuovo peso bias strato nascosto
            
            
        }
            
                                            }
                                            
                                            
                                            
            
            else if (h_synapse[i].dEdw * (h_neuron[i].dEdy *
            d_sigmoid ( h_neuron[i].value ) * i_neuron[j].value) < 0)       {

              
           for ( i = 0; i < hidden_size; i++ )
        {
             // Correggo il peso sinaptico
            for ( j = 0; j < input_size; j++ )
    
                        {


            delta_ij = max( (h_synapse[i].dEdw)*etameno , delta_min);
            
            
            
                delta_w = (h_neuron[i].dEdy *
            d_sigmoid ( h_neuron[i].value ) * i_neuron[j].value) - (h_synapse[i].dEdw);
            
            
            // Applico la modifica al peso sinaptico w = w + delta_w dei neuroni in uscita (uno in questo caso)
            
            
            
            h_synapse[i * ( input_size + 1 ) + j].weight += delta_w;
            }
            
            
            (h_neuron[i].dEdy *
            d_sigmoid ( h_neuron[i].value ) * i_neuron[j].value) = 0;
            
            // Calcolo la modifica del peso del bias delta_w = - eta * dE/dy_j * dy_j/dP_j * dP_j/dw_jk
            
                delta_w = (h_neuron[i].dEdy *
            d_sigmoid ( h_neuron[i].value )) - (h_synapse[i].dEdw);
        
            
            // Aggiungo la correzione del bias w = w + delta_w
            
            
            h_synapse[i * ( input_size + 1 ) + j].weight += delta_w;
            
            
            
            (h_neuron[i].dEdy *
            d_sigmoid ( h_neuron[i].value )) = 0;
            
            
            
        }
            
            
                                            }
                                            
                                            
                                            
            else if (h_synapse[i].dEdw * (h_neuron[i].dEdy *
            d_sigmoid ( h_neuron[i].value ) * i_neuron[j].value) == 0)      {

          
              
           for ( i = 0; i < hidden_size; i++ )
        {
             // Correggo il peso sinaptico
            for ( j = 0; j < input_size; j++ )
    
                        {

                        delta_w = -sign(h_neuron[i].dEdy *
            d_sigmoid ( h_neuron[i].value ) * i_neuron[j].value) * delta_ij;
            
            // Applico la modifica al peso sinaptico w = w + delta_w dei neuroni in uscita (uno in questo caso)
            
            h_synapse[i * ( input_size + 1 ) + j].weight += delta_w;
            }
                        
                        // Calcolo la modifica del peso del bias delta_w = - eta * dE/dy_j * dy_j/dP_j * dP_j/dw_jk
            
            delta_w = -sign(h_neuron[i].dEdy *
            d_sigmoid ( h_neuron[i].value ) ) * delta_ij;
            
            
            // Aggiungo la correzione del bias w = w + delta_w
            
            
            
            h_synapse[i * ( input_size + 1 ) + j].weight += delta_w;
            
            
            }
            
                                            }
        
          
        
        //FINE AGGIORNAMENTO DEI PESI DEI VARI STRATI
 
}//fine del primo for (quello con il numero delle coppie sn)
 
 
 // Calcolo l'errore quadratico medio della rete (MSE) E(x) = SUM( e^2 ) / n_samples
 error /= ( input_size * sn );
 
 printf ("\n");
 
 // Ogni 1000 epoche stampo il log di addestramento
 if ( epochs % 1 == 0 )
 {
 printf( "Epoca #%zu, MSE=%f\n", epochs, error );  //MSE errore della rete
 }
 
 // Incremento il numero delle epoche
 epochs++;


//devo aggiornare il valore del dEdw che cambia per ogni epoca sia per lo strato nascosto che per lo strato output

for (i=0 ; i < hidden_size; i++ )//strato nascosto
    {
        for ( j = 0; j <= input_size; j++ )
        {

                        h_synapse[i].dEdw = h_neuron[i].dEdy * d_sigmoid ( h_neuron[i].value ) * i_neuron[j].value;
                        //printf( " h_syn=%f\n",h_synapse[i].dEdw );
            }
        }


for (i=0 ; i < output_size; i++ )//strato uscita
    {
        for ( j = 0; j <= hidden_size; j++ )
        {

            o_synapse[i].dEdw = o_neuron[i].dEdy * d_sigmoid ( o_neuron[i].value ) * h_neuron[j].value;
            //printf( " o_syn=%f\n",o_synapse[i].dEdw );
        }
        }
        




        
printf ("\n");
printf("valori dEdw dei neuroni intermedi dopo il RBPRO\n\n");
for (i=0 ; i < hidden_size; i++ )//strato nascosto
    {
        for ( j = 0; j <= input_size; j++ )
                {
                  printf( "dEdw_ h_post_syn=%f\n",h_synapse[i*(input_size+1)+j].dEdw );
                }
        }


printf ("\n");
printf("valori dEdw dei neuroni in uscita dopo il RBPRO\n\n");
for (i=0 ; i < output_size; i++ )//strato nascosto
    {
        for ( j = 0; j <= hidden_size; j++ )
                {
                  printf( "dEdw_ o_post_syn=%f\n",o_synapse[i*(input_size+1)+j].dEdw );
                }
        }
 
 
 
 
 
 
 } while ( error > desired_error && epochs < 5 );//fine ciclo do-while


printf ("\n");
 // Log di lavoro
 printf( "Addestramento terminato dopo %zu epoche.\n\n", epochs );
 
}//fine definizione funzione di retropropagazione dell'errore

ecco il secondo codice funzionante

C:
/*rete di tre layers; layer 1 con 2 neuroni; layer 2 con 3 (ne ho provati 200) neuroni; layer 3 con 1 neurone*/

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>

// Precisione dei valori
typedef double T_Precision;


// Struttura di un neurone
struct Neuron
{
 T_Precision value;// Uscita del percettrone
 T_Precision dEdy;//Errore del neurone
};
struct Neuron *i_neuron, *h_neuron, *o_neuron;//variabili di tipo Neuron


// Struttura di una connessione tra due neuroni (sinapsi)
struct Synapse
{
 T_Precision weight; // Peso della connessione
 //T_Precision dEdw;//Errore della connessione
};
struct Synapse *h_synapse, *o_synapse;//variabili di tipo Synapse




//DICHIARAZIONE FUNZIONI

float sigmoid(float x);//dichiarazione funzione sigmoide

float d_sigmoid(float x);//dichiarazione funzione derivata della sigmoide

void run_network( struct Neuron *i_neuron, size_t input_size,    //dichiarazione funzione che fa operare la rete di 3 strati,calcola le uscite di
struct Neuron *h_neuron, struct Synapse *h_synapse, size_t hidden_size, //ogni strato, un percettrone alla volta, fino a determinare le uscite
struct Neuron *o_neuron, struct Synapse *o_synapse, size_t output_size );//della rete

void init_weight( struct Synapse *synapse, size_t layer_size, size_t prev_layer_size );//dichiarazione funzione inizializzazione pesi

void backpropagation( struct Neuron *i_neuron, size_t input_size,
struct Neuron *h_neuron, struct Synapse *h_synapse, size_t hidden_size,
struct Neuron *o_neuron, struct Synapse *o_synapse, size_t output_size,
const T_Precision *dx, const T_Precision *dy, size_t sn,
const T_Precision eta, const T_Precision desired_error );//dichiarazione funzione di retropropagazione dell'errore

//FINE DICHIARAZIONI FUNZIONI
 
 
 
 int main( void )
 
{
    // Inizializzo il generatore di numeri pseudocasuali
    srand( (size_t) time( NULL ) );
 
    // Dimensioni della rete
    const size_t input_size = 2;
    const size_t hidden_size = 3;
    const size_t output_size = 1;
 
    // Creo i neuroni degli strati
    struct Neuron i_neuron[ input_size ];
    struct Neuron h_neuron[ hidden_size];
    struct Neuron o_neuron[ output_size];
 
    // Creo le sinapsi degli strati (+ quella del bias)
    struct Synapse h_synapse[ (input_size + 1) * (hidden_size) ];
    struct Synapse o_synapse[ (hidden_size + 1) * (output_size) ];
 
    // Iteratore
    size_t i, j;
 
    // Numero di esempi dell'insieme di addestramento
    const size_t sn = 4;
 
    // Preparo l'insieme di addestramento per l'operatore XOR//---sn*input_size
    const T_Precision dx[] = { 0,0, 0,1, 1,0, 1,1 };
                        
    const T_Precision dy[] = { 0, 1, 1, 0 };//valori desiderati--- sn*output_size
 
    // Tasso di apprendimento
    const T_Precision eta = 0.5;
    
    // Errore desiderato
    const T_Precision desired_error = 0.0001;
 
    // Addestro la rete neurale
    backpropagation( i_neuron, input_size,
    h_neuron, h_synapse, hidden_size,
    o_neuron, o_synapse, output_size,
    dx, dy, sn, eta, desired_error );
 
    
 
 
 
    // Stampo l'intestazione della tabella
    printf( "[x1]\t[x2]\t[y]\n" );
 
    // Provo tutte le combinazioni degli ingressi
    for ( j = 0; j <= 1; j++ )
    {
        for ( i = 0; i <= 1; i++ )
        {
 
        // Imposto gli ingressi
        i_neuron[0].value = i;
        i_neuron[1].value = j;
 
        // Eseguo la rete neurale
        run_network( i_neuron, input_size,
        h_neuron, h_synapse, hidden_size,
        o_neuron, o_synapse, output_size );
 
        // Stampo gli ingressi e la rispettiva uscita
        printf( "%.0f\t%.0f\t%.0f\n", i_neuron[0].value, i_neuron[1].value, o_neuron[0].value );
        
        }
    }
 
 return 0;
 
}






float sigmoid(float x)//definizione funzione sigmoide
{
     float exp_value;
     float return_value;

     /*** Exponential calculation ***/
     exp_value = exp((double) -x);

     /*** Final sigmoid value ***/
     return_value = 1 / (1 + exp_value);

     return return_value;
}




float d_sigmoid(float x)//definizione funzione derivata della sigmoide
{
     float exp_value;
     float return_value;

     /*** Exponential calculation ***/
     exp_value = exp((double) -x);

     /*** Final sigmoid value ***/
     return_value = (1 / (1 + exp_value))*(1-(1 / (1 + exp_value)));


     return return_value;
}




void run_network(struct Neuron *i_neuron, size_t input_size,    //definizione della funzione che fa operare la rete di 3 strati,calcola le uscite di
struct Neuron *h_neuron,struct Synapse *h_synapse, size_t hidden_size, //ogni strato, un percettrone alla volta, fino a determinare le uscite
struct Neuron *o_neuron, struct Synapse *o_synapse, size_t output_size )//della rete

{

 // Potenziale di attivazione
 float potential;
 // Iteratori
 size_t j, i;

    // Calcolo le uscite dello strato intermedio hidden
    for ( i = 0; i < hidden_size; i++ )
 
        {
            // Azzero il potenziale di attivazione
            potential = 0;
                // Calcolo il potenziale di attivazione
                    for ( j = 0; j < input_size; j++ )
                    {
                        potential += i_neuron[j].value * h_synapse[i * ( input_size + 1 ) + j].weight;
                    }
            // Aggiungo il valore del bias
            potential += h_synapse[i * ( input_size + 1 ) + j].weight;
 
            // Calcolo l'uscita del neurone sulla base del potenziale di attivazione
            h_neuron[i].value = sigmoid( potential ); //uscita del generico neurone nello strato hidden
        }
 
 
 
    // Calcolo le uscite dello strato di uscita
    for ( i = 0; i < output_size; i++ )
        
        {
            // Azzero il potenziale di attivazione
            potential = 0;
                // Calcolo il potenziale di attivazione
                    for ( j = 0; j < hidden_size; j++ )
                    {
                        potential += h_neuron[j].value * o_synapse[i * ( hidden_size + 1 ) + j].weight;
                    }
 
            // Aggiungo il valore del bias
            potential += o_synapse[i * ( hidden_size + 1 ) + j].weight;
 
            // Calcolo l'uscita del neurone sulla base del potenziale di attivazione
            o_neuron[i].value = sigmoid( potential );//uscita del neurone output
        }
}//fine funzione (procedura) run_network






void init_weight( struct Synapse *synapse, size_t layer_size, size_t prev_layer_size )//definizione funzione inizializzazione pesi
{
    // Valore casuale
    T_Precision random_;
    
    // Iteratori
    size_t j, i = 0;
 
    // Inizializzo i pesi sinaptici con dei valori casuali (inizializzo anche il peso del  bias)
    for (i=0 ; i < layer_size; i++ )
    {
        for ( j = 0; j <= prev_layer_size; j++ )
        {
            // Prelevo un valore casuale
            random_ = rand();
            // Imposto il valore del peso tra 0 e 1
            synapse[i * (prev_layer_size + 1) + j].weight = ( sin(random_) * sin(random_));//col seno al quadrato
                                                 //ho valori tra zero e uno
        }
    }
}//fine definizione funzione inizializzazione pesi
 




void backpropagation( struct Neuron *i_neuron, size_t input_size,
struct Neuron *h_neuron, struct Synapse *h_synapse, size_t hidden_size,
struct Neuron *o_neuron, struct Synapse *o_synapse, size_t output_size,
const T_Precision *dx, const T_Precision *dy, size_t sn,
const T_Precision eta, const T_Precision desired_error )//definizione funzione di retropropagazione dell'errore
 
{
     // Errore della rete
    T_Precision error;
 
    // Modifica del peso sinaptico
    T_Precision delta_w;
 
    // Contatore delle epoche
    size_t epochs = 0;
 
    // Iteratori
    size_t t, j, i;
 
    // Log di lavoro
    printf( "Inizio l'addestramento (eta = %.2f, errore desiderato = %f).\n", eta,desired_error );
    
    // Inizializzo i pesi sinaptici con dei valori casuali
    init_weight( h_synapse, hidden_size, input_size ); //inizializzazione peso neuroni dello strato nascosto
    init_weight( o_synapse, output_size, hidden_size );//inizializzazione peso neuroni dello strato output
 
    
    //stampo i pesi inizializzati per lo strato nascosto
    printf("\n");
    printf("pesi iniziali strato nascosto\n");
    for (i=0 ; i < hidden_size; i++ )
    {
        for ( j = 0; j <= input_size; j++ )
        {

                   printf("p#h %zu %zu %.3f\n", j, i * (input_size+1) + j, h_synapse[i * (input_size+1) + j].weight);
                }
        }
 
 
          
    //stampo i pesi inizializzati per lo strato di uscita
    printf("\n");
    printf("pesi iniziali strato di uscita\n");
    for (i=0 ; i < output_size; i++ )
    {
        for ( j = 0; j <= hidden_size; j++ )
        {
                     printf("p#o %zu %zu %.3f\n", j, i * (hidden_size+1) + j, o_synapse[i * (hidden_size+1) + j].weight);
                }
        }
 
            
    
 
 
 
 
 
    // Continuo l'addestramento finché non raggiungo
    // l'errore desiderato (max 50000 epoche)
    do
    {
    // Azzero l'errore della rete (somma degli errori della rete)
    error = 0.0;
    
        
    
    // Ripeto per tutti gli esempi nell'insieme di addestramento
    for ( t = 0; t < sn; t++ )
    {
        
            // Prendo gli ingressi dall'esempio
            for ( i = 0; i < input_size; i++ )
            
            {
                i_neuron[i].value = dx[t * input_size + i];
            }
 
            // Eseguo la rete neurale
            run_network( i_neuron, input_size,
            h_neuron, h_synapse, hidden_size,
            o_neuron, o_synapse, output_size );
 
 
 
 
 
        // Calcolo l'errore dello strato di uscita (in questo caso un neurone)
        for ( i = 0; i < output_size; i++ )
        {
        
            // Calcolo l'errore dell'uscita del neurone dE/dy_i = -(D_i - Y_i)
            o_neuron[i].dEdy = -( dy[t * output_size + i] - o_neuron[i].value );
 
            // Aggiungo l'errore al totale
            error += (( o_neuron[i].dEdy )*( o_neuron[i].dEdy)) ;
        }
 
 
 
         // Calcolo l'errore dello strato intermedio
        for ( i = 0; i < hidden_size; i++ )
            {
            
            // Azzero l'errore dei neuroni dello strato intermedio hidden
            h_neuron[i].dEdy = 0;
            
            // Calcolo l'errore dello strato intermedio dE/dz_k = SUM( dE/dy_j * dy_j/dP_j * dP_j/dz_k )
            for ( j = 0; j < output_size; j++ )
                {
                
                // Calcolo l'errore dell'uscita dei neuroni dello strato intermedio
                h_neuron[i].dEdy += o_neuron[j].dEdy *
                d_sigmoid ( o_neuron[j].value ) * o_synapse[j * ( hidden_size + 1 ) + i].weight;
                }
 
            // Calcolo l'errore dell'uscita del bias
            h_neuron[i].dEdy += o_neuron[j].dEdy *
            d_sigmoid ( o_neuron[j].value ) * o_synapse[j * ( hidden_size + 1 ) + i].weight;
            }
 
 
 
     //    printf("valori delta_w strato di uscita\n");
        // Aggiusto i pesi dello strato di uscita
        for ( i = 0; i < output_size; i++ )
        {
        
            // Correggo il peso sinaptico
            for ( j = 0; j < hidden_size; j++ )
            {
 
            // Calcolo la modifica del peso sinaptico delta_w = - eta * dE/dy_j * dy_j/dP_j * dP_j/dw_jk
            delta_w = - eta * o_neuron[i].dEdy *
            d_sigmoid ( o_neuron[i].value ) * h_neuron[j].value;
            
            
        //    printf("%.3f\n", delta_w);//stampo i delta
                
            // Applico la modifica al peso sinaptico w = w + delta_w dei neuroni in uscita (uno in questo caso)
            o_synapse[i * ( hidden_size + 1 ) + j].weight += delta_w;
            }
 
            // Calcolo la modifica del peso del bias delta_w = - eta * dE/dy_j * dy_j/dP_j * dP_j/dw_jk
            delta_w = - eta * o_neuron[i].dEdy *
            d_sigmoid ( o_neuron[i].value );
            
        //    printf("%.3f\n", delta_w);//stampo il delta del bias
            
            // Aggiungo la correzione del bias w = w + delta_w
            o_synapse[i * ( hidden_size + 1 ) + j].weight += delta_w;
        }
        
        
        printf("valori delta_w strato nascosto\n");
        // Aggiusto i pesi dello strato intermedio
        for ( i = 0; i < hidden_size; i++ )
        {
                
            // Correggo il peso sinaptico dei neuroni dello strato intermedio
            for ( j = 0; j < input_size; j++ )
            {
 
            // Calcolo la modifica del peso sinaptico delta_w = - eta * dE/dz_k * dz_k/dP_k * dP_k/dw_ki
            delta_w = - eta * h_neuron[i].dEdy *
            d_sigmoid ( h_neuron[i].value ) * i_neuron[j].value;
            
            
            printf("%.3f\n", delta_w);//stampo i delta
 
            // Applico la modifica al peso sinaptico w = w + delta_w
            h_synapse[i * ( input_size + 1 ) + j].weight += delta_w;
            
            }
 
            // Calcolo la modifica del peso del bias delta_w = - eta * dE/dz_k * dz_k/dP_k * dP_k/dw_ki
            delta_w = - eta * h_neuron[i].dEdy *
            d_sigmoid ( h_neuron[i].value );
 
            printf("%.3f\n", delta_w);//stampo il delta del bias
            
            // Aggiungo la correzione del bias w = w + delta_w
            h_synapse[i * ( input_size + 1 ) + j].weight += delta_w;
        }//ho un delta_w diverso per ogni neurone
        
 }//fine del primo for
 
 
 // Calcolo l'errore quadratico medio della rete (MSE) E(x) = SUM( e^2 ) / n_samples
 error /= ( input_size * sn );
 
 // Ogni 1000 epoche stampo il log di addestramento
 printf("\n");
 if ( epochs % 1 == 0 )
 {
 printf( "Epoca #%zu, MSE=%f\n", epochs, error );
 
 
        
//stampo i pesi dopo BPRO per lo strato nascosto
    printf("\n");
    printf("pesi dopo BPRO strato nascosto\n");
    for (i=0 ; i < hidden_size; i++ )
    {
        for ( j = 0; j <= input_size; j++ )
        {

                   printf("pB#h %zu %zu %.3f\n", j, i * (input_size + 1) + j,  h_synapse[i * (input_size + 1) + j].weight);
                }
        }
 
 
            
    //stampo i pesi dopo BPRO per lo strato di uscita
    printf("\n");
    printf("pesi dopo BPRO strato di uscita\n");
    for (i=0 ; i < output_size; i++ )
    {
        for ( j = 0; j <= hidden_size; j++ )
        {
                     printf("pB#o %zu %zu %.3f\n", j, i * (hidden_size + 1) + j, o_synapse[i * (hidden_size + 1) + j].weight);
                }
        }
        

//stampo l'errore dopo BPRO per lo strato nascosto
    printf("\n");
    printf("errori dopo BPRO strato nascosto\n");
    for (i=0 ; i < hidden_size; i++ )
    {
        for ( j = 0; j <= input_size; j++ )
        {

                   printf("eB#h %zu %zu %.3f\n", j, i * (input_size + 1) + j, o_neuron[i * (input_size + 1) + j].dEdy);
                }
        }
 
        
            
    //stampo l'errore dopo BPRO per lo strato di uscita
    printf("\n");
    printf("errori dopo BPRO strato di uscita\n");
    for (i=0 ; i < output_size; i++ )
    {
        for ( j = 0; j <= hidden_size; j++ )
        {
                     printf("eB#o %zu %zu %.3f\n", j, i * (hidden_size + 1) + j, h_neuron[i * (hidden_size + 1) + j].dEdy);
                }
        }
        
        


            
        
 }
  
 
 // Incremento il numero delle epoche
 epochs++;
 
 } while ( error > desired_error && epochs < 2 );//fine ciclo do-while
 
 // Log di lavoro
 //printf("\n");
 printf( "Addestramento terminato dopo %zu epoche.\n\n", epochs );
 
}//fine definizione funzione di retropropagazione dell'errore
 

fabio93

Utente Attivo
609
173
CPU
AMD Ryzen 5 2400G
Dissipatore
Arctic Alpine64 Plus
Scheda Madre
Gigabyte GA-AX370-Gaming 3
HDD
Crucial MX500 250 GB, Crucial BX500 240 GB
RAM
G.Skill F4-3200C14D-16GFX FlareX 16 GB
Monitor
HP 2010i
PSU
Corsair TX550M
Case
Sharkoon M25-W
Periferiche
Magicforce 68, Logitech G203
OS
Windows 10 Pro, Fedora 31
Quando ci sono errori di sintassi, il compilatore li segnala, indicando riga e numero di carattere. Nel primo codice ce ne sono un po':
1)
C:
void max ( double T_Precision r,  double T_Precision z);//dichiarazione funzione massimo tra due valori
T_precision è un alias per double quindi non vanno messi entrambi.
2)
C:
void max ( double T_Precision r, double T_Precision z) //definizione funzione massimo
{
     double T_Precision mx;
     double T_Precision r;
     double T_Precision z;
    
     if (x >= y)
        
           mx = r;
     else
          mx = z;       
}
Non puoi dichiarare variabili locali con lo stesso nome dei parametri formali (r e z). E comunque non servono. Inoltre la funzione dovrebbe restituire il valore del massimo. Correzione:
C:
T_Precision max (  T_Precision r,  T_Precision z) //definizione funzione massimo
{
     if (r >= z)
        return r;
     else
        return z;       
}
Analogamente per la funzione min.
3)
Funzione resilient_backpropagation, riga 551:
C:
            (o_neuron[i].dEdy *
            d_sigmoid ( o_neuron[i].value ) * h_neuron[j].value) = 0;
Questa espressione non ha significato: assegna un valore (0) a un altro valore (quello restituito dalla funzione d_sigmoid moltiplicato per il valore del campo dEdy dell'i-esimo elemento dell'array di record o_neuron), non a una variabile!
Idem alle righe 563, 676 e 692.
4) Riga 633:
C:
                delta_w = -sign (h_neuron[i].dEdy *
            d_sigmoid ( h_neuron[i].value ) * delta_ij;
Manca una parentesi prima di ";"

Un consiglio: può sembrare poco importante, ma scrivere il codice in maniera ordinata, con uno stile costante (parentesi sempre negli stessi posti, indentazione uniforme) aiuta molto a non commettere errori di digitazione e a darti una visione a "colpo d'occhio" più efficace, che ti fa programmare meglio, oltre a conferire un aspetto più professionale al codice. Tra l'altro innumerevoli editor di testo lo fanno in automatico, per esempio gedit. Un'altra cosa che mi sento di dirti è di provare a "funzionalizzare" di più il programma: cerca di suddividere il lavoro in più funzioni, in modo tale che ciascuna di esse sia più piccola, quindi più facile da scrivere e con meno probabilità di commettere errori. Quello che si chiama in gergo approccio "divide et impera". Mi riferisco in particolare alla funzione resilient_backpropagation: è davvero lunga, prova a suddividere il lavoro in più sotto-funzioni, ciascuna che faccia una sola cosa.
 

anche_per_il_direttore

Nuovo Utente
63
2
ciao fabio, grazie mille dei consigli e delle correzioni, ci lavorero' sopra la prossima settimana, stavo pensando di testare qualche funzione sul primo codice cercando di visualizzare i risultati nelle varie epoche attraverso gnuplot, sarebbe interessante vedere graficamente come la rete evolve, ciao.
 

anche_per_il_direttore

Nuovo Utente
63
2
salve a tutti, oggi vorrei postare uno pseudo-codice che non so come si comporta e se e possibile fare una cosa del genere.
tutto il costrutto if voglio che stia dentro il ciclo i e il ciclo j, dopodiche vorrei capire ad esempio se supponiamo che i=0, successivamente j=0, a quel punto si verifica o la condizione 1 o la condizione 2 all interno della if, supponiamo che venga verificata la condizione 1, ora la domanda e', supponendo di essere in questo caso l istruzione 1 e l istruzione 2 seguono il ciclo for (ossia i e j) oppure succede qualcosa di diverso??
quello che vorrei cercare di fare e' fare in modo che una volta che la condizione 1 o la condizione 2 sia verificata le istruzioni sotto la condizione verificatasi vengano processate dai cicli for (le due parentesi graffe tra la if e la else "vorrebbero" tenere le due istruzioni separate, ossia l istruzione 2 vorrebbe essere eseguita all uscita del ciclo j)
si puo' fare una cosa cosi' oppure no? e se no ci sono soluzioni? grazie in anticipo, ciao

C:
for (i=0; i<2; i++)
{
    for (j=0; j<3; j++)
    {
        if (condizione 1)
            {
                           
                    istruzione 1;
            }  
                    istruzione 2;
 
        else (condizione 2)
            {
                    istruzione 3;
            }
                    istruzione 4;
                   
    }  //fine ciclo j
       
} //fine ciclo i
[/CODE]
 
Ultima modifica:

fabio93

Utente Attivo
609
173
CPU
AMD Ryzen 5 2400G
Dissipatore
Arctic Alpine64 Plus
Scheda Madre
Gigabyte GA-AX370-Gaming 3
HDD
Crucial MX500 250 GB, Crucial BX500 240 GB
RAM
G.Skill F4-3200C14D-16GFX FlareX 16 GB
Monitor
HP 2010i
PSU
Corsair TX550M
Case
Sharkoon M25-W
Periferiche
Magicforce 68, Logitech G203
OS
Windows 10 Pro, Fedora 31
Non sono sicuro di aver capito benissimo la domanda ma:
1) l'else è sbagliato (e comunque else non vuole una condizione dopo, casomai poteva essere else if) perché non si trova immediatamente dopo un if/else if, ma in mezzo c'è <istruzione 2>, quindi ci vuole un if al suo posto. Il codice corretto diventa:
C:
for (i=0; i<2; i++)
{
    for (j=0; j<3; j++)
    {
        if (condizione 1)
            {
                         
                    istruzione 1;
            }
                    istruzione 2;

        if (condizione 2)
            {
                    istruzione 3;
            }
                    istruzione 4;
                 
    }  //fine ciclo j
     
} //fine ciclo i
2) <istruzione 2> e <istruzione 4> vengono eseguite sempre e comunque, perché si trovano al di fuori delle istruzioni condizionali. Se <condizione 1> è vera viene eseguita anche <istruzione 1>; se <condizione 2> è vera viene eseguita anche <istruzione 2>.
 

anche_per_il_direttore

Nuovo Utente
63
2
Ok, la metto in questo modo, il costrutto

if (condizione1)-----istruzioni -----else if(condizione2)----istruzioni (all'interno del for, come hai giustamente scritto)

e' equivalente al costrutto

if (condizione1)-----istruzioni-----if(condizione2)---- istruzioni (sempre all interno di un for)????

devo purtroppo andare a lavorare, provero' stasera a scrivere i due codici per cercare di spiegarmi meglio, ciao e grazie
 

fabio93

Utente Attivo
609
173
CPU
AMD Ryzen 5 2400G
Dissipatore
Arctic Alpine64 Plus
Scheda Madre
Gigabyte GA-AX370-Gaming 3
HDD
Crucial MX500 250 GB, Crucial BX500 240 GB
RAM
G.Skill F4-3200C14D-16GFX FlareX 16 GB
Monitor
HP 2010i
PSU
Corsair TX550M
Case
Sharkoon M25-W
Periferiche
Magicforce 68, Logitech G203
OS
Windows 10 Pro, Fedora 31
No, i due costrutti non sono equivalenti perché nel primo le due condizioni sono alternative, nel secondo no. Ma sono diversi da quello del post precedente, perché lì c'erano anche due istruzioni non coinvolte dai costrutti if, che venivano eseguite sempre. Il fatto che il tutto sia all'interno di un ciclo for non cambia niente.
 

anche_per_il_direttore

Nuovo Utente
63
2
ok, ho capito cosa intendi dire, sono daccordo ma non mi sono spiegato su quello che vorrei fare.
posto un primo codice
C:
for (i=0; i<3; i++)
{
    for (j=0; j<2; j++)
    {
        p += i+j; //p definita a priori
    }
        p += i+j
}
questo codice "dovrebbe" funzionare cosi':
per i=0
j=0 ; p=p +(0+0)
j=1 ; p=p +(0+1)
a questo punto prima di controllare ancora la condizione j<2 l indice j diventa 2, quando questo accade l istruzione al di fuori del ciclo j viene eseguita e diventa:
p=p + (0+2)

a questo punto viene controllata la condizione j<2 che non risulta verificata e si esce dal ciclo j per riparire con i =1
sei daccordo su questo pezzo di codice? (spero di si perche e' la stessa struttura che ho usato dentro la funzione backpropagation che sembra dare risultati corretti)

ora se entrambi siamo daccordo su questo pezzo di codice quello che vorrei fare adesso e' cercare mantenendo questa struttura di inserire all interno dei due cicli for i e for j una struttura if---else if---else if, dove le condizioni all interno di questa struttura logica dipendono anche loro da i e j ad esempio posto questo secondo pseudo-codice che vorrei fosse contenuto nei cicli for (in pratica vorrei poter escludere dal ciclo j la seconda istruzione), nel codice che hai postato il fatto che si verifichi la <condizione1> piuttosto che la <condizione2> non mi evita che entrambe le <istruzioni2> e le <istruzioni4> vengano eseguite in ogni caso.
nell idea del mio codice una volta fatta la scelta logica tra le condizioni, i due cicli for dovrebbe eseguire le istruzioni presenti solo all'interno della if (se quella e' la condizione verificata al variare di i e j) oppure eseguire le istruzioni all interno della else if (se quella e' la condizione che si verifica) e cosi' via.
credo che per arrivare alla soluzione che auspico devo dividere la struttura in piu cicli for (se hai qualche idea ben venga, ti ringrazio in anticipo, ciao)

C:
if ( i * j >0)
{
 
   metto istruzione1 che voglio che venga eseguita dentro il ciclo j
   (per intenderci quella dove ho scritto "//p definita a priori")
 
   metto istruzione che voglio che venga eseguita al di fuori del ciclo j
   (mi riferisco all istruzione p += i+j senza commento a fianco)
 
}

else if ( i * j <0 )
{
    //come istruzioni strutturate all interno della if di cui sopra
}

else if ( i * j == 0)
{
//idem
}

cambiando argomento posto il codice sulla rete neurale con algoritmo backpropagation che avevo testato sulla funzione XOR adesso adattata (la rete neurale) ad approssimare la funzione seno di x (ho dovuto modificare leggermente il codice soprattutto per lo spazio degli ingressi).
i risultati sono incoraggianti (ho inoltre traslato i valori desiderati del seno che sono compresi tra -1 e 1, traslati tra 0.1 e 0.9, con l intenzione di limitare la dimensione dei pesi delle sinapsi, le formule che ho usato rispettivamente per i valori di ingresso e di uscita desiderata sono:

x = (valore dei gradi sessagesimali) /360
y_desiderata = 0.1 + (0.8 * (seno +1)/2)

PS se qualcuno si vuol prendere la briga di testarli su altre funzioni note (coseno, tangente etc etc) si potrebbe mettere insieme i risultati e ottimizzare l architettura della rete neurale
il prossimo passo (una volta risolto il problema del codice con il costrutto logico if) e' quello di utilizzare gnuplot per visualizzare a video l evoluzione della rete neurale al variare delle epoche di apprendimento
saluti a tutti ---segue il codice

C:
/*rete di tre layers; layer 1 con 1 neurone; layer 2 con 4 (ne ho provati 200) neuroni; layer 3 con 1 neurone*/

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>

// Precisione dei valori
typedef double T_Precision;


// Struttura di un neurone
struct Neuron
{
 T_Precision value;// Uscita del percettrone
 T_Precision dEdy;//Errore del neurone
};
struct Neuron *i_neuron, *h_neuron, *o_neuron;//variabili di tipo Neuron


// Struttura di una connessione tra due neuroni (sinapsi)
struct Synapse
{
 T_Precision weight; // Peso della connessione
 //T_Precision dEdw;//Errore della connessione
};
struct Synapse *h_synapse, *o_synapse;//variabili di tipo Synapse




//DICHIARAZIONE FUNZIONI

float sigmoid(float x);//dichiarazione funzione sigmoide

float d_sigmoid(float x);//dichiarazione funzione derivata della sigmoide

void run_network( struct Neuron *i_neuron, size_t input_size,    //dichiarazione funzione che fa operare la rete di 3 strati,calcola le uscite di
struct Neuron *h_neuron, struct Synapse *h_synapse, size_t hidden_size, //ogni strato, un percettrone alla volta, fino a determinare le uscite
struct Neuron *o_neuron, struct Synapse *o_synapse, size_t output_size );//della rete

void init_weight( struct Synapse *synapse, size_t layer_size, size_t prev_layer_size );//dichiarazione funzione inizializzazione pesi

void backpropagation( struct Neuron *i_neuron, size_t input_size,
struct Neuron *h_neuron, struct Synapse *h_synapse, size_t hidden_size,
struct Neuron *o_neuron, struct Synapse *o_synapse, size_t output_size,
const T_Precision *dx, const T_Precision *dy, size_t sn,
const T_Precision eta, const T_Precision desired_error );//dichiarazione funzione di retropropagazione dell'errore

//FINE DICHIARAZIONI FUNZIONI
 
 
 
 int main( void )
 
{
    // Inizializzo il generatore di numeri pseudocasuali
    srand( (size_t) time( NULL ) );
 
    // Dimensioni della rete
    const size_t input_size = 1;
    const size_t hidden_size = 4;
    const size_t output_size = 1;
 
    // Creo i neuroni degli strati
    struct Neuron i_neuron[ input_size ];
    struct Neuron h_neuron[ hidden_size];
    struct Neuron o_neuron[ output_size];
 
    // Creo le sinapsi degli strati (+ quella del bias)
    struct Synapse h_synapse[ (input_size + 1) * (hidden_size) ];
    struct Synapse o_synapse[ (hidden_size + 1) * (output_size) ];
 
    float i;
    // Iteratore
    size_t  j;
 
    // Numero di esempi dell'insieme di addestramento
    const size_t sn = 17;
 
    // Preparo l'insieme di addestramento valori di ingresso dominio funzione seno//---sn*input_size
    const T_Precision dx[] = { 0.000,0.0625,0.1250,0.1875,0.2500,0.3125,0.3750,0.4375,0.5000,0.5625,0.6250,0.6875,0.7500,0.8125,0.8750,0.9375,1.000 };
                        
    const T_Precision dy[] = { 0.5000,0.6531,0.7828,0.8696,0.9000,0.8696,0.7828,0.6531,0.5000,0.3469,0.2172,0.1304,0.1000,0.1304,0.2172,0.3469,0.5000 };//valori desiderati--- sn*output_size
 
    // Tasso di apprendimento
    const T_Precision eta = 0.3;
    
    // Errore desiderato       
    const T_Precision desired_error = 0.0001;
 
    // Addestro la rete neurale
    backpropagation( i_neuron, input_size,
    h_neuron, h_synapse, hidden_size,
    o_neuron, o_synapse, output_size,
    dx, dy, sn, eta, desired_error );
 
    
    // Stampo l'intestazione della tabella
    printf( "[x1]\t[y]\n" );
 
    
    // Provo tutte le combinazioni degli ingressi
        for ( i = 0; i < sn; i++ )
        {
 
        // Imposto gli ingressi
        i_neuron[0].value = i*0.0625; //3.14/2 * (i-1)
 
        // Eseguo la rete neurale
        run_network( i_neuron, input_size,
        h_neuron, h_synapse, hidden_size,
        o_neuron, o_synapse, output_size );
 
        // Stampo gli ingressi e la rispettiva uscita
        printf( "%.4f\t%.4f\n", i_neuron[0].value, o_neuron[0].value );
        
             }
 
 return 0;
 
}






float sigmoid(float x)//definizione funzione sigmoide
{
     float exp_value;
     float return_value;

     /*** Exponential calculation ***/
     exp_value = exp((double) -x);

     /*** Final sigmoid value ***/
     return_value = 1 / (1 + exp_value);

     return return_value;
}




float d_sigmoid(float x)//definizione funzione derivata della sigmoide
{
     float exp_value;
     float return_value;

     /*** Exponential calculation ***/
     exp_value = exp((double) -x);

     /*** Final sigmoid value ***/
     return_value = (1 / (1 + exp_value))*(1-(1 / (1 + exp_value)));


     return return_value;
}




void run_network(struct Neuron *i_neuron, size_t input_size,    //definizione della funzione che fa operare la rete di 3 strati,calcola le uscite di
struct Neuron *h_neuron,struct Synapse *h_synapse, size_t hidden_size, //ogni strato, un percettrone alla volta, fino a determinare le uscite
struct Neuron *o_neuron, struct Synapse *o_synapse, size_t output_size )//della rete

{

 // Potenziale di attivazione
 float potential;
 // Iteratori
 size_t j, i;

    // Calcolo le uscite dello strato intermedio hidden
    for ( i = 0; i < hidden_size; i++ )
 
        {
            // Azzero il potenziale di attivazione
            potential = 0;
                // Calcolo il potenziale di attivazione
                    for ( j = 0; j < input_size; j++ )
                    {
                        potential += i_neuron[j].value * h_synapse[i * ( input_size + 1 ) + j].weight;
                    }
            // Aggiungo il valore del bias
            potential += h_synapse[i * ( input_size + 1 ) + j].weight;
 
            // Calcolo l'uscita del neurone sulla base del potenziale di attivazione
            h_neuron[i].value = sigmoid( potential ); //uscita del generico neurone nello strato hidden
        }
 
 
 
    // Calcolo le uscite dello strato di uscita
    for ( i = 0; i < output_size; i++ )
        
        {
            // Azzero il potenziale di attivazione
            potential = 0;
                // Calcolo il potenziale di attivazione
                    for ( j = 0; j < hidden_size; j++ )
                    {
                        potential += h_neuron[j].value * o_synapse[i * ( hidden_size + 1 ) + j].weight;
                    }
 
            // Aggiungo il valore del bias
            potential += o_synapse[i * ( hidden_size + 1 ) + j].weight;
 
            // Calcolo l'uscita del neurone sulla base del potenziale di attivazione
            o_neuron[i].value = sigmoid( potential );//uscita del neurone output
        }
}//fine funzione (procedura) run_network






void init_weight( struct Synapse *synapse, size_t layer_size, size_t prev_layer_size )//definizione funzione inizializzazione pesi
{
    // Valore casuale
    T_Precision random_;
    
    // Iteratori
    size_t j, i = 0;
 
    // Inizializzo i pesi sinaptici con dei valori casuali (inizializzo anche il peso del  bias)
    for (i=0 ; i < layer_size; i++ )
    {
        for ( j = 0; j <= prev_layer_size; j++ )
        {
            // Prelevo un valore casuale
            random_ = rand();
            // Imposto il valore del peso tra 0 e 1
            synapse[i * (prev_layer_size + 1) + j].weight = ( sin(random_) * sin(random_));//col seno al quadrato
                                                 //ho valori tra zero e uno
        }
    }
}//fine definizione funzione inizializzazione pesi
 




void backpropagation( struct Neuron *i_neuron, size_t input_size,
struct Neuron *h_neuron, struct Synapse *h_synapse, size_t hidden_size,
struct Neuron *o_neuron, struct Synapse *o_synapse, size_t output_size,
const T_Precision *dx, const T_Precision *dy, size_t sn,
const T_Precision eta, const T_Precision desired_error )//definizione funzione di retropropagazione dell'errore
 
{
     // Errore della rete
    T_Precision error;
 
    // Modifica del peso sinaptico
    T_Precision delta_w;
 
    // Contatore delle epoche
    size_t epochs = 0;
 
    //float k;
    // Iteratori
    size_t t, j, i;
 
    // Log di lavoro
    printf( "Inizio l'addestramento (eta = %.2f, errore desiderato = %f).\n", eta,desired_error );
    
    // Inizializzo i pesi sinaptici con dei valori casuali
    init_weight( h_synapse, hidden_size, input_size ); //inizializzazione peso neuroni dello strato nascosto
    init_weight( o_synapse, output_size, hidden_size );//inizializzazione peso neuroni dello strato output
 
    // Continuo l'addestramento finché non raggiungo
    // l'errore desiderato (max 50000 epoche)
    do
    {
    // Azzero l'errore della rete (somma degli errori della rete)
    error = 0.0;
    
    // Ripeto per tutti gli esempi nell'insieme di addestramento
    for ( t = 0; t < sn; t++ )
    {
        
        
        
            // prendo gli ingressi dell'esempio
        i_neuron[0].value = t*0.0625; //3.14/2 * (i-1)
 
            
        
 
            // Eseguo la rete neurale
            run_network( i_neuron, input_size,
            h_neuron, h_synapse, hidden_size,
            o_neuron, o_synapse, output_size );
 
 
 
 
        // Calcolo l'errore dello strato di uscita (in questo caso un neurone)
        for ( i = 0; i < output_size; i++ )
        {
        
            // Calcolo l'errore dell'uscita del neurone dE/dy_i = -(D_i - Y_i)
            o_neuron[i].dEdy = -( dy[t * output_size + i] - o_neuron[i].value );
 
            // Aggiungo l'errore al totale
            error += (( o_neuron[i].dEdy )*( o_neuron[i].dEdy)) ;
        }
 
 
 
         // Calcolo l'errore dello strato intermedio
        for ( i = 0; i < hidden_size; i++ )
            {
            
            // Azzero l'errore dei neuroni dello strato intermedio hidden
            h_neuron[i].dEdy = 0;
            
            // Calcolo l'errore dello strato intermedio dE/dz_k = SUM( dE/dy_j * dy_j/dP_j * dP_j/dz_k )
            for ( j = 0; j < output_size; j++ )
                {
                
                // Calcolo l'errore dell'uscita dei neuroni dello strato intermedio
                h_neuron[i].dEdy += o_neuron[j].dEdy *
                d_sigmoid ( o_neuron[j].value ) * o_synapse[j * ( hidden_size + 1 ) + i].weight;
                }
 
            // Calcolo l'errore dell'uscita del bias
            h_neuron[i].dEdy += o_neuron[j].dEdy *
            d_sigmoid ( o_neuron[j].value ) * o_synapse[j * ( hidden_size + 1 ) + i].weight;
            }
 
 
 
        // Aggiusto i pesi dello strato di uscita
        for ( i = 0; i < output_size; i++ )
        {
        
            // Correggo il peso sinaptico
            for ( j = 0; j < hidden_size; j++ )
            {
 
            // Calcolo la modifica del peso sinaptico delta_w = - eta * dE/dy_j * dy_j/dP_j * dP_j/dw_jk
            delta_w = - eta * o_neuron[i].dEdy *
            d_sigmoid ( o_neuron[i].value ) * h_neuron[j].value;
 
            // Applico la modifica al peso sinaptico w = w + delta_w dei neuroni in uscita (uno in questo caso)
            o_synapse[i * ( hidden_size + 1 ) + j].weight += delta_w;
            }
 
            // Calcolo la modifica del peso del bias delta_w = - eta * dE/dy_j * dy_j/dP_j * dP_j/dw_jk
            delta_w = - eta * o_neuron[i].dEdy *
            d_sigmoid ( o_neuron[i].value );
 
            // Aggiungo la correzione del bias w = w + delta_w
            o_synapse[i * ( hidden_size + 1 ) + j].weight += delta_w;
        }
 
        // Aggiusto i pesi dello strato intermedio
        for ( i = 0; i < hidden_size; i++ )
        {
                
            // Correggo il peso sinaptico dei neuroni dello strato intermedio
            for ( j = 0; j < input_size; j++ )
            {
 
            // Calcolo la modifica del peso sinaptico delta_w = - eta * dE/dz_k * dz_k/dP_k * dP_k/dw_ki
            delta_w = - eta * h_neuron[i].dEdy *
            d_sigmoid ( h_neuron[i].value ) * i_neuron[j].value;
 
            // Applico la modifica al peso sinaptico w = w + delta_w
            h_synapse[i * ( input_size + 1 ) + j].weight += delta_w;
            
            }
 
            // Calcolo la modifica del peso del bias delta_w = - eta * dE/dz_k * dz_k/dP_k * dP_k/dw_ki
            delta_w = - eta * h_neuron[i].dEdy *
            d_sigmoid ( h_neuron[i].value );
 
            // Aggiungo la correzione del bias w = w + delta_w
            h_synapse[i * ( input_size + 1 ) + j].weight += delta_w;
        }
        
 }//fine del primo for
 
 
 // Calcolo l'errore quadratico medio della rete (MSE) E(x) = SUM( e^2 ) / n_samples
 error /= ( input_size * sn );
 
 // Ogni 1000 epoche stampo il log di addestramento
 if ( epochs % 1000 == 0 )
 {
 printf( "Epoca #%zu, MSE=%f\n", epochs, error );
 }
 
 // Incremento il numero delle epoche
 epochs++;
 
 } while ( error > desired_error && epochs < 50000 );//fine ciclo do-while
 
 // Log di lavoro
 printf( "Addestramento terminato dopo %zu epoche.\n\n", epochs );
 
}//fine definizione funzione di retropropagazione dell'errore
 

fabio93

Utente Attivo
609
173
CPU
AMD Ryzen 5 2400G
Dissipatore
Arctic Alpine64 Plus
Scheda Madre
Gigabyte GA-AX370-Gaming 3
HDD
Crucial MX500 250 GB, Crucial BX500 240 GB
RAM
G.Skill F4-3200C14D-16GFX FlareX 16 GB
Monitor
HP 2010i
PSU
Corsair TX550M
Case
Sharkoon M25-W
Periferiche
Magicforce 68, Logitech G203
OS
Windows 10 Pro, Fedora 31
a questo punto prima di controllare ancora la condizione j<2 l indice j diventa 2, quando questo accade l istruzione al di fuori del ciclo j viene eseguita e diventa:
p=p + (0+2)
a questo punto viene controllata la condizione j<2 che non risulta verificata e si esce dal ciclo j per riparire con i =1
sei daccordo su questo pezzo di codice?
È corretto nei fatti ma il controllo della condizione j < 2 e la conseguente uscita dal ciclo avvengono prima che venga eseguita p=p+(0+2).
Per quanto riguarda lo pseudocodice sotto al posto dell'ultima else if puoi mettere semplicemente un else (senza condizione), perché oltre ai casi i * j > 0 e i * j < 0, resta solo i * j == 0, non ci sono altre possibilità.
 

anche_per_il_direttore

Nuovo Utente
63
2
ciao, si avevo notato il problema sulla else if, ma volevo capire se era chiaro quello che avevo in mente di fare con il ciclo e che nella maniera in cui e' scritto non fa.
comincio a pensare che devo modificare il codice in modo piu radicale per renderlo perfettamente aderente all algoritmo che voglio implementare.
comunque grazie dell aiuto, ciao
 

anche_per_il_direttore

Nuovo Utente
63
2
salve a tutti
questa e' la mia ultima versione del RBPRO (che pero' ancora non funziona come dovrebbe, compilazione ok, ma algoritmo fa qualcosa di altro), come al solito se qualcuno conosce l algoritmo e vuol provare a capire cosa c'e' di sbagliato sarebbe di grande aiuto.
questo algoritmo e' piuttosto banale dal punto di vista matematico, ma aime' l implementazione e' tuttaltro che ovvia (soprattutto per un non informatico)

ecco il codice

C:
/*rete di tre layers; layer 1 con 2 neuroni; layer 2 con 3 (ne ho provati 200) neuroni; layer 3 con 1 neurone*/

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>

// Precisione dei valori
typedef double T_Precision;


// Struttura di un neurone
struct Neuron
{
 T_Precision value;// Uscita del percettrone
 T_Precision dEdy;//Errore del neurone
};
//struct Neuron *i_neuron, *h_neuron, *o_neuron;//variabili di tipo Neuron


// Struttura di una connessione tra due neuroni (sinapsi)
struct Synapse
{
 T_Precision weight; // Peso della connessione
 T_Precision dEdw;//Errore della connessione
 T_Precision delta_ij;//derivata di E rispetto al peso ij (termine che va moltiplicato per eta)
};
//struct Synapse *h_synapse, *o_synapse;//variabili di tipo Synapse




//DICHIARAZIONE FUNZIONI

T_Precision max ( T_Precision r, T_Precision z);//dichiarazione funzione massimo tra due valori

T_Precision min ( T_Precision r, T_Precision z);//dichiarazione funzione minimo tra due valori

int sign (float x);//dichiarazione funzione segno

float sigmoid(float x);//dichiarazione funzione sigmoide

float d_sigmoid(float x);//dichiarazione funzione derivata della sigmoide

void run_network( struct Neuron *i_neuron, size_t input_size,    //dichiarazione funzione che fa operare la rete di 3 strati,calcola le uscite di
struct Neuron *h_neuron, struct Synapse *h_synapse, size_t hidden_size, //ogni strato, un percettrone alla volta, fino a determinare le uscite
struct Neuron *o_neuron, struct Synapse *o_synapse, size_t output_size );//della rete

void init_weight( struct Synapse *synapse, size_t layer_size, size_t prev_layer_size );//dichiarazione funzione inizializzazione pesi


void init_dEdw( struct Synapse *synapse, size_t layer_size, size_t prev_layer_size );//dichiarazione funzione inizializzazione dEdw


void resilient_backpropagation( struct Neuron *i_neuron, size_t input_size,
struct Neuron *h_neuron, struct Synapse *h_synapse, struct Synapse *h_delta, size_t hidden_size,
struct Neuron *o_neuron, struct Synapse *o_synapse, struct Synapse *o_delta, size_t output_size,
const T_Precision *dx, const T_Precision *dy, size_t sn,
const T_Precision etapiu, const T_Precision etameno, const T_Precision desired_error );//dichiarazione funzione di retropropagazione dell'errore

//FINE DICHIARAZIONI FUNZIONI
 
 
 
 int main(void)
 
{
    // Inizializzo il generatore di numeri pseudocasuali
    srand( (size_t) time( NULL ) );
 
    // Dimensioni della rete
    const size_t input_size = 2;
    const size_t hidden_size = 5;
    const size_t output_size = 1;
 
    // Creo i neuroni degli strati
    struct Neuron i_neuron[ input_size ];
    struct Neuron h_neuron[ hidden_size];
    struct Neuron o_neuron[ output_size];
 
    // Creo le sinapsi degli strati (+ quella del bias)
    struct Synapse h_synapse[ (input_size + 1) * (hidden_size) ];
    struct Synapse o_synapse[ (hidden_size + 1) * (output_size) ];
    
    struct Synapse o_delta[ (input_size + 1) * (hidden_size) ];
    struct Synapse h_delta[ (hidden_size + 1) * (input_size) ];
    
    // Iteratore
    size_t i, j;
 
    // Numero di esempi dell'insieme di addestramento
    const size_t sn = 4;
    //T_Precision o_delta;
    //T_Precision h_delta;
 
    // Preparo l'insieme di addestramento per l'operatore XOR//---sn*input_size
    const T_Precision dx[] = { 0,0, 0,1, 1,0, 1,1 };
                        
    const T_Precision dy[] = { 0, 1, 1, 0 };//valori desiderati--- sn*output_size
 
    const T_Precision etapiu = 1.2; 
    const T_Precision etameno = 0.5;
    
    // Tasso di apprendimento
    //const T_Precision eta = 0.5;
    
    // Errore desiderato
    const T_Precision desired_error = 0.0001;
 
    // Addestro la rete neurale
    resilient_backpropagation(i_neuron, input_size,
    h_neuron, h_synapse, h_delta, hidden_size,
    o_neuron, o_synapse, o_delta, output_size,
    dx, dy, sn, etapiu, etameno, desired_error );
 
    
    // Stampo l'intestazione della tabella
    printf( "[x1]\t[x2]\t[y]\n" );
 
    // Provo tutte le combinazioni degli ingressi
    for ( j = 0; j <= 1; j++ )
    {
        for ( i = 0; i <= 1; i++ )
        {
 
        // Imposto gli ingressi
        i_neuron[0].value = i;
        i_neuron[1].value = j;
 
        // Eseguo la rete neurale
        run_network( i_neuron, input_size,
        h_neuron, h_synapse, hidden_size,
        o_neuron, o_synapse, output_size );
 
        // Stampo gli ingressi e la rispettiva uscita
        printf( "%.0f\t%.0f\t%.0f\n", i_neuron[0].value, i_neuron[1].value, o_neuron[0].value );
        
        }
    }
 
 return 0;
 
}



T_Precision max ( T_Precision r, T_Precision z) //definizione funzione massimo
{
    
     if (r >= z)
        
           return r;
     else
          return z;       
}



T_Precision min ( T_Precision r, T_Precision z)//definizione funzione minimo
{
    
     if (r <= z)
        
           return r;
     else
          return z;       
}


int sign (float x)//definizione funzione segno
{
      int sg;
      
      if (x < 0)
      {
        sg = -1;
      }
      else if  (x == 0)
      {
           sg = 0;
      }
      else
      {
       sg = 1;
      }
      return sg;
}
            





float sigmoid(float x)//definizione funzione sigmoide
{
     float exp_value;
     float return_value;

     /*** Exponential calculation ***/
     exp_value = exp((double) -x);

     /*** Final sigmoid value ***/
     return_value = 1 / (1 + exp_value);

     return return_value;
}




float d_sigmoid(float x)//definizione funzione derivata della sigmoide
{
     float exp_value;
     float return_value;

     /*** Exponential calculation ***/
     exp_value = exp((double) -x);

     /*** Final sigmoid value ***/
     return_value = (1 / (1 + exp_value))*(1-(1 / (1 + exp_value)));


     return return_value;
}




void run_network(struct Neuron *i_neuron, size_t input_size,    //definizione della funzione che fa operare la rete di 3 strati,calcola le uscite di
struct Neuron *h_neuron,struct Synapse *h_synapse, size_t hidden_size, //ogni strato, un percettrone alla volta, fino a determinare le uscite
struct Neuron *o_neuron, struct Synapse *o_synapse, size_t output_size )//della rete

{

 // Potenziale di attivazione
 float potential;
 // Iteratori
 size_t j, i;

    // Calcolo le uscite dello strato intermedio hidden
    for ( i = 0; i < hidden_size; i++ )
 
        {
            // Azzero il potenziale di attivazione
            potential = 0;
                // Calcolo il potenziale di attivazione
                    for ( j = 0; j < input_size; j++ )
                    {
                        potential += i_neuron[j].value * h_synapse[i * ( input_size + 1 ) + j].weight;
                    }
            // Aggiungo il valore del bias
            potential += h_synapse[i * ( input_size + 1 ) + j].weight;
 
            // Calcolo l'uscita del neurone sulla base del potenziale di attivazione
            h_neuron[i].value = sigmoid( potential ); //uscita del generico neurone nello strato hidden
        }
 
 
 
    // Calcolo le uscite dello strato di uscita
    for ( i = 0; i < output_size; i++ )
        
        {
            // Azzero il potenziale di attivazione
            potential = 0;
                // Calcolo il potenziale di attivazione
                    for ( j = 0; j < hidden_size; j++ )
                    {
                        potential += h_neuron[j].value * o_synapse[i * ( hidden_size + 1 ) + j].weight;
                    }
 
            // Aggiungo il valore del bias
            potential += o_synapse[i * ( hidden_size + 1 ) + j].weight;
 
            // Calcolo l'uscita del neurone sulla base del potenziale di attivazione
            o_neuron[i].value = sigmoid( potential );//uscita del neurone output
        }
}//fine funzione (procedura) run_network






void init_weight( struct Synapse *synapse, size_t layer_size, size_t prev_layer_size )//definizione funzione inizializzazione pesi
{
    // Valore casuale
    T_Precision random_;
    
    // Iteratori
    size_t j, i = 0;
 
    // Inizializzo i pesi sinaptici con dei valori casuali (inizializzo anche il peso del  bias)
    for (i=0 ; i < layer_size; i++ )
    {
        for ( j = 0; j <= prev_layer_size; j++ )
        {
            // Prelevo un valore casuale
            random_ = rand();
            // Imposto il valore del peso tra 0 e 1
            synapse[i * (prev_layer_size + 1) + j].weight = 5*( sin(random_) * sin(random_));//col seno al quadrato
                                                 //ho valori tra zero e uno
        }
    }
}//fine definizione funzione inizializzazione pesi
 
 
 
 
void init_dEdw( struct Synapse *synapse, size_t layer_size, size_t prev_layer_size )//definizione funzione inizializzazione dEdw
{
    // Valore casuale
    T_Precision random_;
    
    // Iteratori
    size_t  j, i = 0;
 
    // Inizializzo i pesi sinaptici con dei valori casuali (inizializzo anche il peso del  bias)
    for (i=0 ; i < layer_size; i++ )
    {
        for ( j = 0; j <= prev_layer_size; j++ )
        {
            // Imposto il valore del peso tra 0 e 1
            synapse[i * (prev_layer_size + 1) + j].dEdw = 0.1;    //ho valori tra zero e uno
        }
    }
}//fine definizione funzione inizializzazione dEdw



void resilient_backpropagation(struct Neuron *i_neuron, size_t input_size,
struct Neuron *h_neuron, struct Synapse *h_synapse, struct Synapse *h_delta, size_t hidden_size,
struct Neuron *o_neuron, struct Synapse *o_synapse, struct Synapse *o_delta, size_t output_size,
const T_Precision *dx, const T_Precision *dy, size_t sn,
const T_Precision eta_piu, const T_Precision eta_meno , const T_Precision desired_error )//definizione funzione di retropropagazione dell'errore
 
{
     // Errore della rete
    T_Precision error;
 
    // Modifica del peso sinaptico
    
    T_Precision delta_o;
    T_Precision delta_o_eta;
    T_Precision delta_h;
    T_Precision delta_h_eta;
    
    
    
    //valore delta minimo
    const T_Precision delta_min = 0.0025;//exp(-6);
                            
    //valore delta massimo
    const T_Precision delta_max = 50;
                            
                            
    // Contatore delle epoche
    size_t epochs = 0;
 
    // Iteratori
    size_t  i,j,t;//ho aggiunto k per ciclare dentro le if
 
    // tasso di apprendimento positivo
    const T_Precision etapiu = 1.2;
    
    // tasso di apprendimento negativo
    const T_Precision etameno = 0.5;
 
    // Log di lavoro
    printf( "Inizio l'addestramento (etapiu = %.2f,etameno = %.2f, errore desiderato = %f).\n\n", etapiu, etameno, desired_error );
    
    
    
    // Inizializzo e stampo per ogni neurone i pesi sinaptici con dei valori casuali
    init_weight( h_synapse, hidden_size, input_size ); //inizializzazione peso neuroni dello strato nascosto
    init_weight( o_synapse, output_size, hidden_size );//inizializzazione peso neuroni dello strato output
                   /*
    printf("pesi inizializzati dei neuroni intermedi\n\n");
    for (i=0 ; i < hidden_size; i++ )
    {
        for ( j = 0; j <= input_size; j++ )
        {

                    printf( "pesi_ o_syn=%f\n", h_synapse[i*(input_size+1)+j].weight );
                }
        }
        
    
    printf("\n");
    printf("pesi inizializzati dei neuroni in uscita\n\n");
    for (i=0 ; i < output_size; i++ )
    {
        for ( j = 0; j <= hidden_size; j++ )
        {
                     printf( "pesi_ o_syn=%f\n", o_synapse[i*(hidden_size+1)+j].weight );
                }
        }
        
                     */
    
    
    //inizializzo e stampo per ogni neurone i dEdw
    init_dEdw( h_synapse, hidden_size, input_size ); //inizializzazione dEdw peso neuroni dello strato nascosto sono i delta zero
    init_dEdw( o_synapse, output_size, hidden_size );//inizializzazione dEdw peso neuroni dello strato output sono i delta zero
                        /*
    printf("\n");
    printf("valori dEdw inizializzati dei neuroni intermedi\n\n");
    for (i=0 ; i < hidden_size; i++ )
    {
        for ( j = 0; j <= input_size; j++ )
        {
                      printf( "dEdw_ o_syn=%f\n", h_synapse[i*(input_size+1)+j].dEdw );
                }
        }
        
    printf("\n");
    printf("valori dEdw inizializzati dei neuroni in uscita\n\n");
    for (i=0 ; i < output_size; i++ )
    {
        for ( j = 0; j <= hidden_size; j++ )
        {
                      printf( "dEdw_ o_syn=%f\n",o_synapse[i*(hidden_size+1)+j].dEdw );
                }
        }
                          */
    
    // Continuo l'addestramento finché non raggiungo
    // l'errore desiderato (max 50000 epoche)
    do
    {
    // Azzero l'errore della rete (somma degli errori della rete)
    error = 0.0;
    
    // Ripeto per tutti gli esempi nell'insieme di addestramento
    for ( t = 0; t < sn; t++ )
    {       //primo for
        
            // Prendo gli ingressi dall'esempio
            for ( i = 0; i < input_size; i++ )
            
            {
                i_neuron[i].value = dx[t * input_size + i];//per sn=0 (0,0); sn=1 (1,0); sn=2 (0,1); sn=3 (1,1)
            }
 
            // Eseguo la rete neurale mi da i valori dei vari neuroni (le y)
            run_network( i_neuron, input_size,
            h_neuron, h_synapse, hidden_size,
            o_neuron, o_synapse, output_size );
 
             // CALCOLO ERRORI DEGLI STRATI
        // Calcolo l'errore dello strato di uscita (in questo caso un neurone)
        for ( i = 0; i < output_size; i++ )
        {
        
            // Calcolo l'errore dell'uscita dei neuroni dello strato di uscita dE/dy_i = -(D_i - Y_i); nell'esempio ErrA e ErrB
            o_neuron[i].dEdy = -( dy[t * output_size + i] - o_neuron[i].value );
 
            // Aggiungo l'errore all'errore totale della rete
            error += (( o_neuron[i].dEdy )*( o_neuron[i].dEdy)) ;
        }
 
 
         // Calcolo l'errore dei neuroni dello strato intermedio
        for ( i = 0; i < hidden_size; i++ )
            {
            
            // Azzero l'errore dei neuroni dello strato intermedio hidden
            h_neuron[i].dEdy = 0;
            
            // Calcolo l'errore dello strato intermedio dE/dz_k = SUM( dE/dy_j * dy_j/dP_j * dP_j/dz_k )
            for ( j = 0; j < output_size; j++ )
                {
                
                // Calcolo l'errore dell'uscita dei neuroni dello strato intermedio; nell'esempio ErrC=deltaA*wa1 +deltaB*wb1; deltaA = ErrA * A*(1-A)
                    //ErrA = o_neuron[i].dEdy ; A*(1-A) = d_sigmoid( o_neuron[j].value ); wa1;wb1= o_synapse[j * ( hidden_size + 1 ) + i].weight (sono le sinapsi //provenienti dai neuroni dello strato hidden)
                h_neuron[i].dEdy += o_neuron[j].dEdy *
                d_sigmoid ( o_neuron[j].value ) * o_synapse[j * ( hidden_size + 1 ) + i].weight;
                }
 
            // Calcolo l'errore dell'uscita del bias
            h_neuron[i].dEdy += o_neuron[j].dEdy *
            d_sigmoid ( o_neuron[j].value ) * o_synapse[j * ( hidden_size + 1 ) + i].weight;
            }
                 //FINE CALCOLO ERRORI DEGLI STRATI
 
 
 
 
 
 
 
 
                 //CALCOLO LE VARIAZIONI DELL ERRORE RISPETTO AI PESI
 
 
        // calcolo le variazioni delta dei pesi a meno del parametro eta per i neuroni dello strato di uscita; Delta A* C; Delta A * F; DeltaA per il bias
        for ( i = 0; i < output_size; i++ )
        {
        
            // Correggo il peso sinaptico
            for ( j = 0; j < hidden_size; j++ )
            {
 
            // Calcolo delta_w = dE/dy_j * dy_j/dP_j * dP_j/dw_jk; nell'esempio DeltaC=ErrC*C(1-C); deltaC * G e' la variazione del peso a meno di eta; G e'l'uscita del neurone dello strato precedente
             o_delta[ i *(hidden_size +1) +j ].delta_ij = o_neuron[i].dEdy *
            d_sigmoid ( o_neuron[i].value ) * h_neuron[j].value;
 
 
 
 
                if     (o_synapse[i].dEdw * o_delta[ i *(hidden_size +1) +j ].delta_ij  > 0)  {

            
                            delta_o = min( (o_synapse[i].dEdw)*etapiu , delta_max);
                
                
                delta_o_eta = -sign (o_delta[ i *(hidden_size +1) +j ].delta_ij ) * delta_o;
            
 
            // Applico la modifica al peso sinaptico w = w + delta_w dei neuroni in uscita (uno in questo caso)
            o_synapse[i * ( hidden_size + 1 ) + j].weight += delta_o_eta;//nuovi pesi strato uscita delta w (t+1)
            
            
                                                    }
                                            
        else if (o_synapse[i].dEdw * o_delta[ i *(hidden_size +1) +j ].delta_ij  < 0)   {
            
            delta_o = max( (o_synapse[i].dEdw)*etameno , delta_min);
                
            
                    o_synapse[i * ( hidden_size + 1 ) + j].weight = (o_delta[ i *(hidden_size +1) +j ].delta_ij) - (o_synapse[i].dEdw);
            
            
                o_delta[ i *(hidden_size +1) +j ].delta_ij = 0;
        
                                                                                         }
        else                                                                       {
            
            
            delta_o_eta = -sign (o_delta[ i *(hidden_size +1) +j ].delta_ij ) * delta_o;
            
 
            // Applico la modifica al peso sinaptico w = w + delta_w dei neuroni in uscita (uno in questo caso)
            o_synapse[i * ( hidden_size + 1 ) + j].weight += delta_o_eta;
            
            
                            
                                                        }
                                            
                                                        
    }
 
            // Calcolo la modifica del peso del bias delta_w = - eta * dE/dy_j * dy_j/dP_j * dP_j/dw_jk
             o_delta[ i *(hidden_size +1) +j ].delta_ij = o_neuron[i].dEdy *
            d_sigmoid ( o_neuron[i].value );
            
            
            
                if     ((o_synapse[i].dEdw * o_delta[ i *(hidden_size +1) + j ].delta_ij )  > 0)  {

                                                                         //maggiore di zero
            // Calcolo la modifica del peso del bias delta_w = - eta * dE/dy_j * dy_j/dP_j * dP_j/dw_jk
            
                            delta_o = min( (o_synapse[i].dEdw)*etapiu , delta_max);
                
                
                delta_o_eta = -sign (o_delta[ i *(hidden_size +1) + j ].delta_ij ) * delta_o;
            
 
            // Applico la modifica al peso sinaptico w = w + delta_w dei neuroni in uscita (uno in questo caso)
            o_synapse[i * ( hidden_size + 1 ) + j].weight += delta_o_eta;//nuovi pesi strato uscita delta w (t+1)
            
                              
                                                                                                        }
                                                                      
        else if ((o_synapse[i].dEdw * o_delta[ i *(hidden_size +1) + j ].delta_ij ) < 0)           {
            
            delta_o = max( (o_synapse[i].dEdw)*etameno , delta_min);
                
            
                    o_synapse[i * ( hidden_size + 1 ) + j].weight = (o_delta[ i *(hidden_size +1) +j ].delta_ij) - (o_synapse[i].dEdw);
            
            
                o_delta[ i *(hidden_size +1) + j ].delta_ij = 0;
        
            //o_neuron[i].dEdy *
            //d_sigmoid ( o_neuron[i].value ) * h_neuron[j].value == 0;
            
                                                                                                            }
    
        else                                                                                            {
                        
        
            delta_o_eta = -sign (o_delta[ i *(hidden_size +1) + j ].delta_ij ) * delta_o;
            
            
            
 
 
            // Applico la modifica al peso sinaptico w = w + delta_w dei neuroni in uscita (uno in questo caso)
            o_synapse[i * ( hidden_size + 1 ) + j ].weight += delta_o_eta;
              
                                                        }
    
 
 }


                          
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
 
 
 
        // calcolo le variazioni delta dei pesi a meno del parametro eta per i neuroni dello strato intermedio; Delta C* G; Delta C * H; DeltaC per il bias
        for ( i = 0; i < hidden_size; i++ )
        {
                
            // Correggo il peso sinaptico dei neuroni dello strato intermedio
            for ( j = 0; j < input_size; j++ )
            {
 
            // Calcolo la modifica del peso sinaptico delta_w = - eta * dE/dz_k * dz_k/dP_k * dP_k/dw_ki
             h_delta[ i *(input_size +1) +j ].delta_ij = h_neuron[i].dEdy *
            d_sigmoid ( h_neuron[i].value ) * i_neuron[j].value;
 
 
 
                if     ((h_synapse[i].dEdw * h_delta[ i *(input_size +1) +j ].delta_ij ) > 0)      {
                        
                
                        delta_h = min( (h_synapse[i].dEdw)*etapiu , delta_max);
                
                
                delta_h_eta = -sign (h_delta[ i *(input_size +1) +j ].delta_ij ) * delta_h;
                
                h_synapse[i * ( input_size + 1 ) + j].weight += delta_h_eta;
                                    
                                                                                                }
            
            
            
            
            
            
            else if ((h_synapse[i].dEdw * h_delta[ i *(input_size +1) +j ].delta_ij ) < 0)       {


            delta_h = max( (h_synapse[i].dEdw)*etameno , delta_min);
                
            
                    h_synapse[i * ( input_size + 1 ) + j].weight = (h_delta[ i *(input_size +1) +j ].delta_ij) - (h_synapse[i].dEdw);
            
            
                h_delta[ i *(input_size +1) +j ].delta_ij = 0;
            
                        
                                                                                                }
            
                                            
                                            
            else                                                                               {

                           delta_h_eta = -sign (h_delta[ i *(input_size +1) +j ].delta_ij ) * delta_h;
            
            
            
 
 
            // Applico la modifica al peso sinaptico w = w + delta_w dei neuroni in uscita (uno in questo caso)
            h_synapse[i * ( input_size + 1 ) + j].weight += delta_h_eta;
            
            
                                                                                                }
                
 
 
 
 
 
 
                        
            // Applico la modifica al peso sinaptico w = w + delta_w
            //h_synapse[i * ( input_size + 1 ) + j].weight += delta_w;
            
            }
 
            // Calcolo la modifica del peso del bias delta_w = - eta * dE/dz_k * dz_k/dP_k * dP_k/dw_ki
            h_delta[ i *(input_size +1) +j ].delta_ij = h_neuron[i].dEdy *
            d_sigmoid ( h_neuron[i].value );
 
 
 
                if     ((h_synapse[i].dEdw * h_delta[ i *(input_size +1) + j ].delta_ij )  > 0)  {

                                                                         //maggiore di zero
            // Calcolo la modifica del peso del bias delta_w = - eta * dE/dy_j * dy_j/dP_j * dP_j/dw_jk
            
                            delta_h = min( (h_synapse[i].dEdw)*etapiu , delta_max);
                
                
                delta_h_eta = -sign (h_delta[ i *(input_size +1) + j ].delta_ij ) * delta_h;
            
            
            
            
 
            // Applico la modifica al peso sinaptico w = w + delta_w dei neuroni in uscita (uno in questo caso)
            h_synapse[i * ( input_size + 1 ) + j].weight += delta_h_eta;//nuovi pesi strato uscita delta w (t+1)
            
                
            
            
            
                              
                                                                                   }
                                                                      
        else if ((h_synapse[i].dEdw * h_delta[ i *(input_size +1) + j ].delta_ij )  > 0)           {
            
            delta_h = max( (h_synapse[i].dEdw)*etameno , delta_min);
                
            
                    h_synapse[i * ( input_size + 1 ) + j].weight = (h_delta[ i *(input_size +1) +j ].delta_ij) - (h_synapse[i].dEdw);
            
            
                h_delta[ i *(input_size +1) +j ].delta_ij = 0;
        
            //o_neuron[i].dEdy *
            //d_sigmoid ( o_neuron[i].value ) * h_neuron[j].value == 0;
            
                                                                                                   }
    
        else                                                                                            {
                        
        
            delta_h_eta = -sign (h_delta[ i *(input_size +1) +j ].delta_ij ) * delta_h;
            
            
            
 
 
            // Applico la modifica al peso sinaptico w = w + delta_w dei neuroni in uscita (uno in questo caso)
            h_synapse[i * ( input_size + 1 ) + j].weight += delta_h_eta;
              



                                                                                                       }
 
 
 
 
                        
            // Aggiungo la correzione del bias w = w + delta_w
            //h_synapse[i * ( input_size + 1 ) + j].weight += delta_w;
}
        
 
 
 
 
 

                                    
        //FINE AGGIORNAMENTO DEI PESI DEI VARI STRATI
 
 
 
 
}//fine del primo for (quello con il numero delle coppie sn)
 
 
 // Calcolo l'errore quadratico medio della rete (MSE) E(x) = SUM( e^2 ) / n_samples
 error /= ( input_size * sn );
 
 //printf ("\n");
 
 // Ogni 1000 epoche stampo il log di addestramento
 if ( epochs % 1000 == 0 )
 {
 printf( "Epoca #%zu, MSE=%f\n", epochs, error );  //MSE errore della rete
 }
 
 
 
 
 /*
 
 
 
for (i=0 ; i < hidden_size; i++ )//strato nascosto
    {
        for ( j = 0; j <= input_size; j++ )
        {

                        //h_synapse[i].dEdw = h_neuron[i].dEdy * d_sigmoid ( h_neuron[i].value ) * i_neuron[j].value;
                        printf( " h_syn=%f\n",h_synapse[i].dEdw * (h_neuron[i].dEdy *
            d_sigmoid ( h_neuron[i].value ) * i_neuron[j].value) );
            }
        }

                          
for (i=0 ; i < output_size; i++ )//strato uscita
    {
        for ( j = 0; j <= hidden_size; j++ )
        {

            //o_synapse[i].dEdw = o_neuron[i].dEdy * d_sigmoid ( o_neuron[i].value ) * h_neuron[j].value;
            printf( " o_syn=%f\n",o_synapse[i].dEdw * (o_neuron[i].dEdy *
            d_sigmoid ( o_neuron[i].value ) * h_neuron[j].value));   
        }
        }
   */     
 
 
 
 
 
 
 // Incremento il numero delle epoche
 epochs++;
                          
 
 
} while ( error > desired_error && epochs < 50000 );//fine ciclo do-while


//printf ("\n");
 // Log di lavoro
 printf( "Addestramento terminato dopo %zu epoche.\n\n", epochs );
 
}//fine definizione funzione di retropropagazione dell'errore
 

Ci sono discussioni simili a riguardo, dai un'occhiata!

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!

Discussioni Simili