From 67dfb2fe9211c08d6295708c1d1613dedbf4b4d1 Mon Sep 17 00:00:00 2001 From: mirimatcode Date: Sat, 22 Feb 2025 15:43:02 +0100 Subject: [PATCH] configurato per mnist 1000 epoche pronto al test --- classificatore_singolo | Bin 25608 -> 21344 bytes classificatore_singolo.c | 245 +++++++++--------- classificatore_singolo_xor | Bin 0 -> 21344 bytes percettroni.h | 504 ++++++++++++++++++++++--------------- xor_manager.h | 8 +- 5 files changed, 435 insertions(+), 322 deletions(-) create mode 100755 classificatore_singolo_xor diff --git a/classificatore_singolo b/classificatore_singolo index 31ab327d179fd0531e7d579ab8282fd8c084d3f7..5b9c29a760678bacfd701652cabf82515dde2878 100755 GIT binary patch literal 21344 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 diff --git a/classificatore_singolo.c b/classificatore_singolo.c index 1518e8e..da47838 100644 --- a/classificatore_singolo.c +++ b/classificatore_singolo.c @@ -1,186 +1,197 @@ #include #include "percettroni.h" -//Scelgo quale categoria voglio identificare. nel caso dello xor -1 -#define CATEGORIA -1 -#define NUM_LAYERS 3 -#define PERCETTRONI_LAYER_0 4 -#define MAX_EPOCHE 1000000 +// Scelgo quale categoria voglio identificare. nel caso dello xor -1 +#define CATEGORIA 7 +#define NUM_LAYERS 4 +#define PERCETTRONI_LAYER_0 64 +#define MAX_EPOCHE 1000 byte get_out_corretto(byte); -void stampa_layer_indirizzo(Layer*); +void stampa_layer_indirizzo(Layer *); void stampa_tempo(time_t[], int); -void main() { +void main() +{ time_t tempo_epoche[MAX_EPOCHE]; srand(time(NULL)); - Dataset *set_appoggio = crea_dataset_xor();//get_dataset(file_immagini, file_label); + Dataset *set_appoggio = get_dataset(file_immagini, file_label); - if(set_appoggio == NULL) + if (set_appoggio == NULL) return; Dataset set = *set_appoggio; free(set_appoggio); ReteNeurale rete_neurale; ReteNeurale *puntatore_rete = caricaReteNeurale(file_pesi); - if(puntatore_rete == NULL) { + if (puntatore_rete == NULL) + { rete_neurale = inizializza_rete_neurale(NUM_LAYERS, PERCETTRONI_LAYER_0, N_INPUTS); - } else { + } + else + { rete_neurale = *puntatore_rete; free(puntatore_rete); printf("Caricate impostazioni rete neurale da file\n"); } + //rete_neurale = inizializza_rete_neurale(NUM_LAYERS, PERCETTRONI_LAYER_0, N_INPUTS); + int corrette = 0; + printf("Numero elementi nel dataset: %d\n", set.size); - //ADDESTRAMENTO - for(int i = 0; i < MAX_EPOCHE; i++) { - - //printf("Epoca %d\n", i); - //stampa_tempo(tempo_epoche, i); - int corrette = 0; - double errore_totale = 0.0; + // ADDESTRAMENTO + for (int i = 0; i < MAX_EPOCHE; i++) + { + /* if (corrette == 4) + { + printf("\nConvergo in epoche: %d\n", i); - for(int indice_set = 0; indice_set < set.size; indice_set++) { + // stampa_risultati_layer_multi(p_ext_1, p_ext_2, pout); + for (int j = 0; j < 4; j++) + { + double **risultato = elabora_sigmoidi(rete_neurale, set.istanze[j]); - //sigmoidi è un array bidimensionale, la prima dimensione identifica il layer, la seconda il percettrone nel layer - // sigmoidi[indice_layer][indice_percettrone] - double **sigmoidi = (double **)malloc(sizeof(double*) * NUM_LAYERS); - - //Il layer di ingresso ha bisogno di una funzione a parte perchè prende byte come input - sigmoidi[0] = (double*)malloc(sizeof(double) * PERCETTRONI_LAYER_0); - sigmoidi[0] = funzioni_attivazione_layer_byte(rete_neurale.layers[0], set.istanze[indice_set].dati); - - //Calcolo le sigmoidi in tutti gli altri layer - for(int j = 1; j < NUM_LAYERS; j++) { - sigmoidi[j] = (double*)malloc(sizeof(double) * rete_neurale.layers[j].size); - sigmoidi[j] = funzioni_attivazione_layer_double(rete_neurale.layers[j], sigmoidi[j-1]); + printf("Input: [%d,%d] -> probabilità: %f -> risultato atteso: %d\n", set.istanze[j].dati[0], set.istanze[j].dati[1], risultato[NUM_LAYERS - 1][0], set.istanze[j].classificazione); } + break; + } */ + + // printf("Epoca %d\n", i); + // stampa_tempo(tempo_epoche, i); + corrette = 0; + double errore_totale = 0.0; + + for (int indice_set = 0; indice_set < set.size -1; indice_set++) + { + //printf("Qui ci arrivo %d\n", indice_set); + double **sigmoidi = elabora_sigmoidi(rete_neurale, set.istanze[indice_set]); + + /* for(int k = 0; k < rete_neurale.size; k++) + for(int j = 0; j < rete_neurale.layers[k].size; j++) + printf("sigmoide[%d][%d] = %f\n", k, j, sigmoidi[k][j]); */ + byte output_corretto = get_out_corretto(set.istanze[indice_set].classificazione); - //Se prevede male - if(previsione(sigmoidi[NUM_LAYERS-1][0]) != output_corretto) { + double **gradienti = (double **)malloc(sizeof(double *) * NUM_LAYERS); - //gradienti è un array bidimensionale, la prima dimensione identifica il layer, la seconda il percettrone nel layer - //gradienti[indice_layer][indice_percettrone] - //Questo vettore identifica i gradienti dei percettroni - double **gradienti = (double**)malloc(sizeof(double*) * NUM_LAYERS); + // Alloco la dimensione per ogni layer + for (int indice_layer = 0; indice_layer < NUM_LAYERS; indice_layer++) + { + gradienti[indice_layer] = (double *)malloc(sizeof(double) * rete_neurale.layers[indice_layer].size); + } - //Alloco la dimensione per ogni layer - for(int indice_layer = 0; indice_layer < NUM_LAYERS; indice_layer++) { - gradienti[indice_layer] = (double*)malloc(sizeof(double) * rete_neurale.layers[indice_layer].size); - } + - /* Gestione dell'errore - Funzione di perdita -> errore quadratico medio: (risultato_esatto - previsione)^2 - Gradiente dell'errore rispetto all'attivazione = derivata(funzione_perdita) * derivata(sigmoide_out) - = -(risultato_esatto - previsione) * (sigmoide_out * (1 - sigmoide_out)) - - //Per ogni percettrone sugli altri layer: - - calcolare derivata della propria sigmoide - - gradiente dell'errore retropropagato = peso del ne - - */ - - //Derivata funzione di perdita - double gradiente_errore = -(output_corretto - sigmoidi[NUM_LAYERS-1][0]); - //Derivata funzione attivazione - double derivata_sigmoide_out = sigmoidi[NUM_LAYERS-1][0] * (1 - sigmoidi[NUM_LAYERS-1][0]); - if (derivata_sigmoide_out == 0.0) derivata_sigmoide_out = 1; - - //Gradiente del percettrone output - gradienti[NUM_LAYERS-1][0] = gradiente_errore * derivata_sigmoide_out; + // Derivata funzione di perdita + // printf("output_corretto = %d, previsione: %f\n", output_corretto, sigmoidi[NUM_LAYERS - 1][0]); + double gradiente_errore = (output_corretto - sigmoidi[NUM_LAYERS - 1][0]); - //Ricorda di partire dal penultimo layer in quanto l'ultimo è già fatto - discesa_gradiente(rete_neurale, sigmoidi, gradienti); + errore_totale += pow(gradiente_errore, 2); - /* A questo punto ho tutti i gradienti dei percettroni, non mi resta che trovare i gradienti dei pesi e correggerli - */ + // Derivata funzione attivazione + double derivata_sigmoide_out = sigmoidi[NUM_LAYERS - 1][0] * (1.0 - sigmoidi[NUM_LAYERS - 1][0]); + // if (derivata_sigmoide_out == 0.0) derivata_sigmoide_out = 1; - //Correggo il livello output - for(int indice_peso = 0; indice_peso < rete_neurale.layers[NUM_LAYERS-1].percettroni[0].size; indice_peso ++) { - //Determino gradiente del peso - double gradiente_peso = gradienti[NUM_LAYERS-1][0] * sigmoidi[NUM_LAYERS-2][indice_peso]; - rete_neurale.layers[NUM_LAYERS-1].percettroni[0].pesi[indice_peso] -= gradiente_peso * LRE; - } - rete_neurale.layers[NUM_LAYERS-1].percettroni[0].bias -= gradienti[NUM_LAYERS-1][0] * LRE; - - + // Gradiente del percettrone output + gradienti[NUM_LAYERS - 1][0] = gradiente_errore * derivata_sigmoide_out; - //Applico la correzione dal penultimo layer andando indietro fino al secondo (il primo si fa diverso) - for(int indice_layer = NUM_LAYERS - 2; indice_layer >= 0; indice_layer--) { - //Applico la correzione a tutti i percettroni del layer dal primo a seguire - for(int indice_percettrone = 0; indice_percettrone < rete_neurale.layers[indice_layer].size; indice_percettrone++) { - //Devo prendere il gradiente del percettrone e moltiplicarlo con gli input associati ai pesi - if(indice_layer != 0) { - correggi_pesi_percettrone_double(&rete_neurale.layers[indice_layer].percettroni[indice_percettrone], indice_layer, sigmoidi, gradienti[indice_layer][indice_percettrone]); - } else { - correggi_pesi_percettrone_byte(&rete_neurale.layers[0].percettroni[indice_percettrone], set.istanze[indice_set], gradienti[0][indice_percettrone], indice_percettrone); - } - + discesa_gradiente(rete_neurale, sigmoidi, gradienti); + + // A questo punto ho tutti i gradienti dei percettroni, non mi resta che trovare i gradienti dei pesi e correggerli + + // Correggo il livello output + for (int indice_peso = 0; indice_peso < rete_neurale.layers[NUM_LAYERS - 1].percettroni[0].size; indice_peso++) + { + // Determino gradiente del peso + double gradiente_peso = gradienti[NUM_LAYERS - 1][0] * sigmoidi[NUM_LAYERS - 2][indice_peso]; + rete_neurale.layers[NUM_LAYERS - 1].percettroni[0].pesi[indice_peso] += gradiente_peso * LRE; + } + rete_neurale.layers[NUM_LAYERS - 1].percettroni[0].bias += gradienti[NUM_LAYERS - 1][0] * LRE; + + // Applico la correzione dal penultimo layer andando indietro fino al secondo (il primo si fa diverso) + for (int indice_layer = NUM_LAYERS - 2; indice_layer >= 0; indice_layer--) + { + // Applico la correzione a tutti i percettroni del layer dal primo a seguire + for (int indice_percettrone = 0; indice_percettrone < rete_neurale.layers[indice_layer].size; indice_percettrone++) + { + // Devo prendere il gradiente del percettrone e moltiplicarlo con gli input associati ai pesi + if (indice_layer != 0) + { + correggi_pesi_percettrone_double(&rete_neurale.layers[indice_layer].percettroni[indice_percettrone], indice_layer, sigmoidi, gradienti[indice_layer][indice_percettrone]); + } + else + { + correggi_pesi_percettrone_byte(&rete_neurale.layers[0].percettroni[indice_percettrone], set.istanze[indice_set], gradienti[0][indice_percettrone], indice_percettrone); } } - - - - //gradienti[NUM_LAYERS-1][0] = (output_corretto - sigmoidi[NUM_LAYERS-1][0]); - errore_totale += gradienti[NUM_LAYERS-1][0]; - - //correggi_layer_interni(&rete_neurale, gradienti, sigmoidi); - //correggi_layer_input(&rete_neurale.layers[0], gradienti, sigmoidi, set.istanze[indice_set].dati, NUM_LAYERS); } - else + + if (previsione(sigmoidi[NUM_LAYERS - 1][0]) == output_corretto) { corrette++; } + } - if(corrette == 4) { - printf("\tConvergo all'epoca %d\n", i); - break; + printf("Errore: %f, risposte corrette: %d/%d\n", errore_totale / 10000, corrette, set.size); + // printf("\tRisposte corrette: %d\n", corrette); + + /* if (i == MAX_EPOCHE - 1) + { + printf("\nUltima epoca (%d), stato della rete:\n", i); + double **risultato; + for (int j = 0; j < 4; j++) + { + risultato = elabora_sigmoidi(rete_neurale, set.istanze[j]); + printf("Input: [%d,%d] -> probabilità: %f -> previsione: %d -> risultato attesto: %d\n", set.istanze[j].dati[0], set.istanze[j].dati[1], risultato[NUM_LAYERS - 1][0], previsione(risultato[NUM_LAYERS - 1][0]), set.istanze[j].classificazione); + for (int k = 0; k < rete_neurale.size; k++) + for (int j = 0; j < rete_neurale.layers[k].size; j++) + printf("sigmoide[%d][%d] = %f\n", k, j, risultato[k][j]); } - } - - printf("Errore: %f\n", errore_totale / 4); - printf("\tRisposte corrette: %d\n", corrette); - - if(corrette == set.size) { - break; - } + } */ } - //salvaReteNeurale(file_pesi, &rete_neurale); + salvaReteNeurale(file_pesi, &rete_neurale); } -//Questa funzione ritorna 1 se la categoria è quella che voglio individuare, altrimenti 0 -byte get_out_corretto(byte categoria) { - if(CATEGORIA != -1) { - if(categoria == CATEGORIA) +// Questa funzione ritorna 1 se la categoria è quella che voglio individuare, altrimenti 0 +byte get_out_corretto(byte categoria) +{ + if (CATEGORIA != -1) + { + if (categoria == CATEGORIA) return 1; else return 0; } - else return categoria; + else + return categoria; } -void stampa_layer_indirizzo(Layer *layer) { - for(int i = 0; i < layer->size; i++) { +void stampa_layer_indirizzo(Layer *layer) +{ + for (int i = 0; i < layer->size; i++) + { printf("Percettrone %d ->", i); - for(int j = 0; j < layer->percettroni->size; j++) { - printf("\t peso %d, valore: %f",j, layer->percettroni[i].pesi[j]); + for (int j = 0; j < layer->percettroni->size; j++) + { + printf("\t peso %d, valore: %f", j, layer->percettroni[i].pesi[j]); layer->percettroni[i].pesi[j] += 1; } printf("\n"); } } -void stampa_tempo(time_t tempo_epoche[], int i) { +void stampa_tempo(time_t tempo_epoche[], int i) +{ time(&tempo_epoche[i]); - if(i > 0) { - double tempo_trascorso_epoca = difftime(tempo_epoche[i], tempo_epoche[i-1]); + if (i > 0) + { + double tempo_trascorso_epoca = difftime(tempo_epoche[i], tempo_epoche[i - 1]); double tempo_trascorso_totale = difftime(tempo_epoche[i], tempo_epoche[0]); int minuti_epoca = (int)tempo_trascorso_epoca / 60; int secondi_epoca = (int)tempo_trascorso_epoca % 60; diff --git a/classificatore_singolo_xor b/classificatore_singolo_xor new file mode 100755 index 0000000000000000000000000000000000000000..d0b75e9cd3cff022791fc875bc19e73a4af62567 GIT binary patch literal 21344 zcmeHPe|%KcmA{h^i3rT33yRk2*a`xL2od=JiUwieVG~3l6|FiB$t0ON$)uARj0i4v zjLYi~m)g?Ou5GQ`c5T=8gRAmMEyx6w1j=f3QR5c3V~g#K&^98q(Nbr>=iGbWym`r3 z?e6EZ`v*6l%z5|xy62vA-u*T6-rxIbmX^3&LYGo;g`nE46%tde2@^pFEkG_=bRX~#k)iygIv(5w1ARY5IB?jpIAl1nK$4TbWj zhT5Ox6Z)U0^f_TQXjH2CQwXPAhmv!`C5m4|YJR=##|a;iXrZBQ z?^?(yS1XPW20F~w>Gq1mVWsk?hC0tK4u{sxopW)xVP-hg8t<6dF>mh7xpOMpBbCx{ zvWrrIa%$O%I#IGoqzI?wUBbon(}AN>qUxGXyksNQNuCPf=${I~3HYb55dDmEANp3~ z(tnQpdi$*e z_*F&lj~Bszw+Q~~BKUtOf*1bft84uY!Dz54)E)~)SJy5MM_Plc18c)U;rBPSL|Xmr zu|PED_e<6h8G{{dqAhZ}Xp6_%MO!c$jYJ^~x%%7u_06~W8v~)RXp9Df^bu$f!H!Uj znCqJZQPB`;Y>b6kK#Q~mTLl=x;Yht`k-+cA9bB($XbFT`MSC>R+5q+S9RYu1s5KA{ zt%q!VIMN;zZP8F`tWh-H9u38U0+KCstIwq?s0%hxZBFGJs@F@(vYO>rE%sMcR?Qds z@{&2$W&WzF@=~}E_kStw(Gu&Au4R3cg_G1Wa1zZWUV|Ks5nlY8U;Y|~Kj?6wg5tvU zp8$zY<#DE$iLsy)ZbB$Djz*EQR6Tx92t!ecxIoG4`AE+LD^;?0tNBLb^-b{LN^ZuQ zH*~$*f%nXkd?^S1JcaLb;4jns*GM^Z56t4|WebZ&C4NqlZ(Y3j^A$n}S)PE%%fE7!kCb($)(o49^I)oF^%wsHMSRHvyidn?z!NOf8oWLI*1 zJ=JN7%vN(fN_AQyWM^^x^His$LDtLlwN$66Gwb2{jZ~*8Gb^}$9o1>7%nrT}#N?}~ z?xA{`>sL{orp9bP*B4Noro?Otb@K1*-z_&^xWzDkWh9Oau3YV#otnMh=vr6>CAo>8 zyF!Q)jg{{6?|}#c(6w+r6c}A)RRrb_#U>&&=Yferb9yfAK7SMOJ*^=4PiOv1O9)JR z-!KP_p5I?-^bD06u6@P}@5d%U!5i5Al7jMFy3u|9lDs_Gw`t+C&@bYb)ES9|d%-CT z^NrXzBf0P{;Byn{3?oyIzV9o000`I3Pv`A@x-oxE`9b=!P2jDA4kT8!VQ%a*%y?=K zxhyjdE-_4BW={n&B9r?I*V0DP*JpH1?E3_@{IX&8X8tHCgGOTGpopIhcRa?#-poIN z(hXH2+lZutWD1h^_e2unSU&l&jEA=_l52`qCrmwRZ!(lZtnpL^l?CP z!~Wy$=?9LxJ!NN~C&Y304L!%*Yf`9>tKj-gJvXzqRY(p4$>$+w9j??{+^lgPn+tCff zTty~5XqbyVR+n~dcofZ=z5!6A?aA6qgYoIHY*(x-GxQ!Qu^Yce8gJIYwY%80qsX=Y zNQ|5P%7#k z2ARzB0X?-3acNCueu?&w0Y1=Xq)gvI7?a4j=KK2MqY+)o_Qb|M5uXmJbh55bMtBrO zI7yZtG+&0%xABm{t~t8U!I^l|gD509W7El6XxMM`yiOX*wfKy@c*56*BHuFBWB%(L!GL@ zIAq3=+Z%CnAQ)yXvV9T<-%y=4+oB+-&_B{pV++k78+v~{Z-9}E+Ydn@m_=ixXEBO5a&M$+1W z8jM~#gNAy2Ct#yExYP);q>aq&HGP=gx|_12@X2^gCfvp-8j7^x zG{pehHTEU4mM7M(b1P^N9>d)!RqK!J10d6IA|2bca)?c*)R;F+J9igR#7%0SfLuLN zK|Z&58AIJyA?I21uXp`jnjZ?fepq(h(Z%_`!|pB1==OjwkQMWN1MV%fI%eCgnTYR* z_z|Se01Zr-(dDghXVQ11puaSjaxx>!Wwi7->Z!#jOM@xKH7L)Fz*SCT$7`3+*l|NK zCcYJrW_%}PlGUF1J|ur!&H))HFj&jil@_$QhEfQWit6&MYQ)6-O?ITs_+j0XX1Xzv z=1a;d+&fb$rBl#XoBmK{Px0xb*zKRB|6jjZ7aYe+~9;4Y^G8J6Xkk~qFYP~{nJOqDcs2+<{3T8bxOQElca zT8`75=TRKPOd*EM@wX_Sk5Ix7^1Xhe4%c5agD z2#ENFPtpeSscR9aJv>k}U_gPweyMN(;OGLVWFf0L8&%WL+@F63(XO(a#>*HyfNF1N z4K;((+qqI*Wnae;QDQd{M!7rZB3+V9GxtIGYAMXI%Pe3GtF_#_oK4)xWG7)UGlf!o z9N_A&Np_J{HOWr0nJ3V@k4-|~aG3McwIpf2f@R>_#`o#i#eC1bvwZWI8uR%YEKMJw zCDGl_c$vGio8*&4nsM(G?wwf9Nv=d{5|3Q7K7hZv#J#iMNbaWC3^RMky|day^AR>- z``7`EINw4B^EMze{}}R*yXs2prXH8N?|ToqmVFebZh7CT6>Mi4IC?wR;FCO_{dWY^ zGK{eQTmITW>mtivTS>F_m$Mo6R|?5-HZ0!U`5Ex;@xr*wPmXe)Z3m*a^CoU zrnrfgE}aj8pH?XsQy7w5&2N&QgmMtO$j@rg&ORTmZWxBQO;6%1)3$Bue3%SRcC!7J zDawQ!mMsvKx!Bed9KynD+PJagNL@Vh}> zD0CLPH93tfz?4uZz)e+`_jWd*KYYyHL32}Qv-Z>Fs3vw3731m`;j|>P;x@6?=dwMy z=G{hud5>Z7qgqUEBOUo{HIlQE+{&=&wCnQIaH~)pWm9zD_h1C-IDwn`2ez=0zYCkI zp(v`J4Srp7N_5w;9viXYnyv}1CCM(b>yWAyFnFn&JsYf+`w5$O|Nm_6nMHHFHI{BB%{t1? zW_TxpTRIgp>57GUDGocXOcXl^1ggq8s2 zrvIdH^JMO_`T0IK&c%+pw$h3ThoSP27Kfonp&@^uXAW)lo!qqX(1 zXiQ{&e1xq12-=X77$82HK-t&Pq?%f=2|h_HPuMSbAAHiiWhTbOJ@k!P<`$Tf@C`8o zFGGjiTi%5Gt%EPMp)})%lD`vmMQ*wE-A$R(42n$E4VK1t;{Pxq0(u`mVyY*LP0~;d6v>kTZ?Vw@XX?=HVeOrqdo+_t2@DV&fzd^K@XfPJ^w*}inm22^n z$(C09xbx!J>{++X47CKBg6)-|hK@^S#@F6~UrE}C;lSEpn2EC$F-p556d(PjGw5v% zhQk4GW4v{JDAF4A@-H^0PGfY?8)|{>P;2PJ^4AAq!KO$w6co3wwKs5406!s(#iIdl zLon=Z4B?lkg=G4DXh2#34j9xDY=NEt8eSZThDa}rX^Y?osKgcWk~d%^REC4z26TXQ zj#(UOT^EctMZBR_Z?G*=-yB@vo!lUQmAAYVKTloY{oLe+8Iv1s_RhS*+ZK(i4Xh1? zL$RkH1YaZJqM`P9I2MRSyn$FO*dCGc(pSVYMvSQojGiKlI#;=br61n zOTyuc$OQp(Ggu#N2)4p3FfSl~*mw|Kc+{c@ap#1eEPH+ZJy%l9g&0&&*6_K>x{?>w z5_qazA1}S^5me|mgl(_oa%sRF|CP)20siopxm-CWo!ei}<)#8Y3upiaFkFTK&-*oo zO~4y5TRaYU4yN@(fJ*>R0N#z&*#z7UH~u!4n*;c8HkVrixbDqdt^;ryc52%Jw_yX_ z4d}v2%K+e~u@X56XaJsz?f&|AbGgd_sgRviTDOUES<}(0JP{O%ZV(!Ks|u}IOqf|x-U^$azC>$PYR^pfoHdq z=dnD`5zy|1uW9FF*Hc=>rm!s(mv18uDZ8GMpRtm2fund`f%stGm)8-LZ4jN}Xn?-Z z-bU#>tFO(#2N72~hPG@dIm8OQKy3#7Jj8hg;$+d$*U}{=mJN?k8;JdLV6k{g_FHuN z#`+!5A1k2$#G)Sq-OR{bv*b&gEE~t7?U#^KVY>~bO>BS{I%fcX0di|P_8gYH0UJMY zy440fr*aWaO7NSOJkJ^?v!B~QzYz2)*kb7@ooU&y74*3{nYzD#-X#M?I!~2T9ysNJ zQyw_wfm0qh<$?cq9?;Ke>F2U&8mID_1lBW5zjf5nK*1u&`L79gmC@Knww4%#hlMpjiNA$B? zlO(&aKNCbKB_=Z0NCqrtxb!J`z23&5A{Xn~AzD+RX#9}6&~}$AdBrAl`#28f{y>yj zaTvz+?Mfa;XI$5I;NX?(jf#$~0M~WD*@*vx59|4HN858%9xPSxvkEpUxK6=)75til zKTvR|g8LMFS;5~Z_>O|7;YSQq&Qx%Uf^!vIs^Di8l-xo*xKdv+td_O(mHIhD{aoQ? zvm|BN;>8QRQ}M*~H1F&=l~t9qy;ZZSE}b>IYM!JQ`=s!X5^wRjypv}nJbufJQX%y7 z>sn?uE?nX)D?c@U8RI7kXB>WjhP}wP?S=gmRHcUqoaIO0|CktWy`O>ij$o?C|495% z;47g2VWnT^yL>)-yqLlp2_bk-1Kw@;_u}7Kz6Zoe`kyF*-$(cox6tE?)_1T7f12^* z#TqrB@E!~}dfs)Ub|)0UPXV6#+wJJ@Eao3CD%60&`&sC}O5tx%jqqL?_!Yo=0iEUZ zz*o={wzDK^z|C=W_wzKd11s)kMYnecx$r?FJh+&e#&QO{%mDEMG@FiI7cqHEXtPcm;+e3|X*o(tVe|xC4 zDH4wOJ0j7_db}I}Gl$=2_?KR{sMhBBNWK+X?!6D=iF?o;DcLwRl@p!KODFt7!^&y zn7<(q3$zDgAN&%C<=5ct3k{)Gf4n`|z;AIVXoFuMG2&Yx{H$NTxw5&d(Kcs80bWz#_pMlhmr~#`y`?SSkI^|c2o3EKe>2_>0T0n@A|frJ`iOk# zL_s_4f$+M(bvS!pA-@zr{PoGYs1JneBjJF*DH>=9(LuPsA=F-v!*h07Bp&l~aAGlP zZ*6R@}MDI5wQ5%JE9Py@X@qwxI~R{L{A5Ppb6E#8oPrG>>n$!G66f0v`ay%7E& zUVb6pc2OXp-=a}~RLg2Puj0 z5)X2b&1vYrj4AtRuECyen(3zuof^Dm9SY~;oTm=Xq%{P zjl_bLO|9`td?y2wVs|LiqN|qAj0Ku(3~S>dy!t29Aeg;5(B3R68}4XD6B5Rvl7jDn z=xddNiXXHnLPY}Vsx2H7m275ZEZBi-zJDvD5%xi4u-V@j4YUOP%?*&%H7Vf_M56&1 zN)q}SiUUYcv>Jgfd{lA+QW-K!RMtmYT9AU)sP{Kt(Eg96WDNUU=*N##G}QY)iIu$i zn&7AKPg@}^KTpYPSPh!J==G__&BcXXzC+1t=+%r0>h+jLFTsUfe!G&_@IuX4ME-i< zaakd5SLEwA^V^ra}7tmXAST0^~W1`8L` zVJ}}mh4!dgUhhjatWwO{e$A)hU7*vRSJ(BvSHoMCy!NrSU!g@8E+{5iUhlg#)cbDT zzLwYh|GJXDN-NYGbOrUkpX6zY;gtU_aO4xM-&zl-b%8$L01Fpq{?Pi^F7H)x8df_T zu9q7c{)UQeI1#o{jc{e8t$+NQiHZz z>-(8QUhj7`d_*%U=xl$#L;hAg@j^vIXZt#Sk_+oNT#U!Rx^46C(OW1vocy}3;V;4F zw#n;rtL_gee-yHmJGyDy!C~me=rI zQ0(&h+$*ExcUY40Ld$7b0%5znK4;ioE%}|tB3e$XrTdd`+J3#h?^p6pern5J#;Nva z*^#)`^3MBD%iEzNMOo8ewNj{VY`Tr;Qrn})4;m)4?Mi~d;8Iz8)j`zlYF@fs9V|@R Of3@T|(;?ufivI?0|ECWC literal 0 HcmV?d00001 diff --git a/percettroni.h b/percettroni.h index 284394c..b3fac51 100644 --- a/percettroni.h +++ b/percettroni.h @@ -6,28 +6,31 @@ char *file_pesi = "rete_pesi.bin"; char *file_immagini = "mnist/t10k-images.idx3-ubyte"; char *file_label = "mnist/t10k-labels.idx1-ubyte"; -//#include "mnist/mnist_manager.h" -//#include "cifar_10/cifar10_manager.h" -#include "xor_manager.h" +#include "mnist/mnist_manager.h" +// #include "cifar_10/cifar10_manager.h" +//#include "xor_manager.h" // Siccome il char è un byte che rappresenta il valore tra 0 e 255. Per evitare confusioni definisco il tipo "byte" come in Java typedef unsigned char byte; -double LRE = 0.5; +double LRE = 2; double soglia_sigmoide = 0.5; -typedef struct { +typedef struct +{ double *pesi; double bias; int size; } Percettrone; -typedef struct { +typedef struct +{ Percettrone *percettroni; int size; } Layer; -typedef struct { +typedef struct +{ Layer *layers; int size; } ReteNeurale; @@ -38,37 +41,34 @@ Percettrone inzializza_percettrone(int); ReteNeurale inizializza_rete_neurale(int, int, int); Layer inizializza_layer(int, int); -double sigmoide_byte(Percettrone, byte*, int); -double sigmoide_double(Percettrone, double*, int); -double *funzioni_attivazione_layer_byte(Layer, byte*); -double *funzioni_attivazione_layer_double(Layer, double*); - -void correggi_layer_interni(ReteNeurale*, double**, double**); -void correggi_layer_input(Layer*, double**, double**, byte*, int); - -void discesa_gradiente(ReteNeurale, double**, double**); -double calcola_gradiente_disceso(ReteNeurale, int, int, double**); -void correggi_pesi_percettrone_double(Percettrone*, int, double**, double); -void correggi_pesi_percettrone_byte(Percettrone*, Istanza, double, int); +double sigmoide(Percettrone p, double*); +double **elabora_sigmoidi(ReteNeurale, Istanza); +void discesa_gradiente(ReteNeurale, double **, double **); +double calcola_gradiente_disceso(ReteNeurale, int, int, double **); +void correggi_pesi_percettrone_double(Percettrone *, int, double **, double); +void correggi_pesi_percettrone_byte(Percettrone *, Istanza, double, int); int previsione(double); -void salvaReteNeurale(const char*, ReteNeurale*); -ReteNeurale *caricaReteNeurale(const char*); +void salvaReteNeurale(const char *, ReteNeurale *); +ReteNeurale *caricaReteNeurale(const char *); -//Questa funzione genera un valore reale random compreso nell'intervallo [-1, 1] -double randomico() { +/* + ################# INIZIALIZZAZIONI ################################ +*/ +// Questa funzione genera un valore reale random compreso nell'intervallo [-1, 1] +double randomico() +{ // Genero numeri nell'intervallo [-1,1] - return ((double)(rand() % 101 * 0.01 * 2 ) -1); + return ((double)(rand() % 101 * 0.01 * 2.0) -1.0); } -//Questa funzione inizializza il percettrone allocando la memoria in base al numero dei pesi che voglio ed inizializza il loro valore usando randomico() -Percettrone inizializza_percettrone(int n_pesi) { +Percettrone inizializza_percettrone(int n_pesi) +{ Percettrone p; - p.pesi = (double*) malloc(sizeof(double) * n_pesi); - for(int i = 0; i < n_pesi; i++) { + p.pesi = (double *)malloc(sizeof(double) * n_pesi); + for (int i = 0; i < n_pesi; i++) { p.pesi[i] = randomico(); - //printf("peso[%d]: %f\n",i, p.pesi[i]); } p.bias = randomico(); @@ -78,41 +78,14 @@ Percettrone inizializza_percettrone(int n_pesi) { return p; } -ReteNeurale inizializza_rete_neurale(int numero_layers, int numero_percettroni_iniziali, int numero_input) { - ReteNeurale r; - r.layers = (Layer*)malloc(sizeof(Layer) * numero_layers); - r.size = numero_layers; - - //Funzione esponenziale inversa layer 5 - for (int livello = 0; livello < numero_layers; livello++) { - double esponente = (double)livello / (double)numero_layers; - double frazione = (double)1 / (double)numero_percettroni_iniziali; - - int numero_percettroni_livello = (int)((double)numero_percettroni_iniziali * pow(frazione, esponente)); - if(livello == numero_layers -1) - numero_percettroni_livello = 1; - - //printf("esponente %f -> frazione: %f\n", esponente, frazione); - printf("Layer %d -> percettroni: %d\n", livello, numero_percettroni_livello); - - if(livello == 0) - r.layers[livello] = inizializza_layer(numero_percettroni_livello, numero_input); - else - r.layers[livello] = inizializza_layer(numero_percettroni_livello, r.layers[livello-1].size); - } - - return r; -} - -//Questa funzione serve ad inizializzare il singolo layer con il numero di percettroni che vogliamo -//Ogni percettrone a sua volta viene automaticamente inizializzato con il numero di pesi che vogliamo e coi valori di partenza -Layer inizializza_layer(int n_percettroni, int n_pesi) { +Layer inizializza_layer(int n_percettroni, int n_pesi) +{ Layer layer; layer.percettroni = (Percettrone *)malloc(sizeof(Percettrone) * n_percettroni); - for(int i = 0; i < n_percettroni; i++) { + for (int i = 0; i < n_percettroni; i++) + { layer.percettroni[i] = inizializza_percettrone(n_pesi); - } layer.size = n_percettroni; @@ -120,179 +93,173 @@ Layer inizializza_layer(int n_percettroni, int n_pesi) { return layer; } -//Questa funzione viene usata per il primo livello perchè ha un vettore di byte (unsigned char) in input -double sigmoide_byte(Percettrone p, byte *valori, int n_input) { - - double sommatoria = 0.0; - //printf("valori: [%d][%d]", valori[0], valori[1]); - //printf("pesi: [%f][%f]", p.pesi[0], p.pesi[1]); +ReteNeurale inizializza_rete_neurale(int numero_layers, int numero_percettroni_iniziali, int numero_input) +{ + ReteNeurale r; + r.layers = (Layer *)malloc(sizeof(Layer) * numero_layers); + r.size = numero_layers; - for(int i = 0; i < n_input; i++) { - sommatoria += (valori[i] * p.pesi[i]); + // Funzione esponenziale inversa layer 5 + for (int livello = 0; livello < numero_layers; livello++) + { + double esponente = (double)livello / (double)numero_layers; + double frazione = (double)1 / (double)numero_percettroni_iniziali; + + int numero_percettroni_livello = (int)((double)numero_percettroni_iniziali * pow(frazione, esponente)); + if (livello == numero_layers - 1) + numero_percettroni_livello = 1; + + // printf("esponente %f -> frazione: %f\n", esponente, frazione); + printf("Layer %d -> percettroni: %d\n", livello, numero_percettroni_livello); + + if (livello == 0) + r.layers[livello] = inizializza_layer(numero_percettroni_livello, numero_input); + else + r.layers[livello] = inizializza_layer(numero_percettroni_livello, r.layers[livello - 1].size); } - //printf("sommatoria= %f\n", sommatoria); - double funzione = sommatoria + p.bias; - double potenza_e = exp(-funzione); - //printf("potenza_e= %f\n", potenza_e); - //formula sigmoide - double risultato = 1 / ( 1 + potenza_e); - //printf("risultato= %f\n", risultato); - return risultato; + + return r; } -//Questa funzione viene usata per gli altri livelli dove gli input sono double, ossia i valori della sigmoide dei livelli precedenti -double sigmoide_double(Percettrone p, double *valori, int n_input) { + +/* + ################# PREVISIONI ################################ +*/ + + +double sigmoide(Percettrone p, double *valori) +{ double sommatoria = 0.0; - for(int i = 0; i < n_input; i++) { + for (int i = 0; i < p.size; i++) { sommatoria += (valori[i] * p.pesi[i]); + //printf("valore [%f] peso[%f] ", valori[i], p.pesi[i]); } - double funzione = sommatoria + p.bias; - //printf("sommatoria= %f\n", sommatoria); - double potenza_e = exp(-funzione); - //printf("potenza_e= %f\n", potenza_e); - //formula sigmoide - double risultato = 1 / ( 1 + potenza_e); - //printf("risultato= %f\n", risultato); + sommatoria += p.bias; + double risultato = 1.0 / (1.0 + exp(-sommatoria)); + //printf(" sommatoria %f -> %f\n",sommatoria, risultato); return risultato; } -//Questa funzione calcola tutte le funzioni di attivazione dei percettroni del layer che prende dei byte come inputs -double *funzioni_attivazione_layer_byte(Layer layer, byte *inputs) { - - double *funzioni = (double*)malloc(sizeof(double) * layer.size); - - for(int i = 0; i < layer.size; i++) { - funzioni[i] = sigmoide_byte(layer.percettroni[i], inputs, layer.percettroni[i].size); - //printf("\tsigmoide layer input %f\n", funzioni[i]); - } - - return funzioni; -} - -//Questa funzione calcola tutte le funzioni di attivazione dei percettroni del layer che prende dei double come inputs (le sigmoidi del livello precedente) -double *funzioni_attivazione_layer_double(Layer layer, double *inputs) { - - double *funzioni = (double*)malloc(sizeof(double) * layer.size); - - for(int i = 0; i < layer.size; i++) { - funzioni[i] = sigmoide_double(layer.percettroni[i], inputs, layer.percettroni[i].size); - //printf("\tsigmoide layer %d: %f\n", i, funzioni[i]); - } - - return funzioni; -} - -//Questa funzione restituisce il valore 0,1 in base alla soglia di attivazione della funzione sigmoide -int previsione(double valore) { - if(valore >= soglia_sigmoide) +int previsione(double valore) +{ + if (valore >= soglia_sigmoide) return 1; else return 0; } + +void discesa_gradiente(ReteNeurale rete, double **sigmoidi, double **gradienti) +{ + //printf("Qui?\n"); + // For che scorre i layer dal penultimo al primo QUINI SIZE -2 + for (int indice_layer = rete.size - 2; indice_layer >= 0; indice_layer--) + { + //printf("layer: %d ", indice_layer); + // printf("Mi trovo nel layer %d, ho %d percettroni\n", indice_layer, rete.layers[indice_layer].size); + // For che scorre i percettroni del layer partendo dal primo + // Per ogni percettrone mi devo prendere il gradiente disceso dal livello sopra e moltiplicarlo per la derivata di attivazione + for (int indice_percettrone = 0; indice_percettrone < rete.layers[indice_layer].size; indice_percettrone++) + { + //printf("percettrone: %d ", indice_percettrone); + double derivata_attivazione = sigmoidi[indice_layer][indice_percettrone] * (1.0 - sigmoidi[indice_layer][indice_percettrone]); - - - -//Questa funzione prende la matrice dei gradienti e la matrice delle sigmoidi per correggere tutti i layer tranne quello di ingresso -void correggi_layer_interni(ReteNeurale *rete, double **gradienti, double **sigmoidi) { - - for(int indice_layer = rete->size-1; indice_layer > 0; indice_layer--) { - for(int indice_percettrone = 0; indice_percettrone < rete->layers[indice_layer].size; indice_percettrone++) {//Numero percettroni - - for(int indice_peso = 0; indice_peso < rete->layers[indice_layer].percettroni[indice_percettrone].size; indice_peso++) {//Numero pesi - gradienti[indice_layer][indice_percettrone] = gradienti[rete->size-1][0] * (sigmoidi[indice_layer][indice_percettrone] * (1 - sigmoidi[indice_layer][indice_percettrone])); - rete->layers[indice_layer].percettroni[indice_percettrone].pesi[indice_peso] += (gradienti[indice_layer][indice_percettrone] * LRE * sigmoidi[indice_layer-1][indice_percettrone]); - //rete->layers[indice_layer].percettroni[indice_percettrone].pesi[indice_peso] += (gradienti[rete->size-1][0] * LRE * sigmoidi[indice_layer-1][indice_percettrone]); - } - rete->layers[indice_layer].percettroni[indice_percettrone].bias += (gradienti[indice_layer][indice_percettrone] * LRE); - //printf("bias: %f\n", rete->layers[indice_layer].percettroni[indice_percettrone].bias); - } - } -} -//Questa funzione prende tutti i parametri della precedente + gli input passati dal dataset per correggere il layer di ingresso -void correggi_layer_input(Layer *layer, double **gradienti, double **sigmoidi, byte *inputs, int n_layers) { - //L'indice del layer d'ingresso che prende byte per input - int indice_layer = 0; - for(int indice_percettrone = 0; indice_percettrone < layer->size; indice_percettrone++) {//Numero percettroni - for(int indice_peso = 0; indice_peso < layer->percettroni->size; indice_peso++) { //Numero pesi - - gradienti[indice_layer][indice_percettrone] = gradienti[n_layers-1][0] * (sigmoidi[indice_layer][indice_percettrone] * (1 - sigmoidi[indice_layer][indice_percettrone])); - layer->percettroni[indice_percettrone].pesi[indice_peso] += (gradienti[indice_layer][indice_percettrone] * LRE * inputs[indice_peso]); - //layer->percettroni[indice_percettrone].pesi[indice_peso] += (gradienti[n_layers-1][0] * LRE * inputs[indice_peso]); - } - layer->percettroni[indice_percettrone].bias += (gradienti[n_layers-1][0] * LRE); - } -} - - - - - - -void discesa_gradiente(ReteNeurale rete, double **sigmoidi, double **gradienti) { - //For che scorre i layer dal penultimo al primo QUINI SIZE -2 - for(int indice_layer = rete.size -2; indice_layer >= 0; indice_layer--) { - //printf("Mi trovo nel layer %d, ho %d percettroni\n", indice_layer, rete.layers[indice_layer].size); - - //For che scorre i percettroni del layer partendo dal primo - //Per ogni percettrone mi devo prendere il gradiente disceso dal livello sopra e moltiplicarlo per la derivata di attivazione - for(int indice_percettrone = 0; indice_percettrone < rete.layers[indice_layer].size; indice_percettrone++) { - - double derivata_attivazione = sigmoidi[indice_layer][indice_percettrone] * (1 - sigmoidi[indice_layer][indice_percettrone]); - - //Passo anche l'indice del percettrone perchè corrisponde all'indice del peso del livello sopra + // Passo anche l'indice del percettrone perchè corrisponde all'indice del peso del livello sopra double gradiente_disceso = calcola_gradiente_disceso(rete, indice_layer + 1, indice_percettrone, gradienti); - + gradienti[indice_layer][indice_percettrone] = gradiente_disceso * derivata_attivazione; } + //printf("\n"); } + //printf("Qui ?\n"); } -double calcola_gradiente_disceso(ReteNeurale rete, int livello, int indice_peso, double **gradienti) { - //printf("Qui ci arrivo\n"); +double calcola_gradiente_disceso(ReteNeurale rete, int livello, int indice_peso, double **gradienti) +{ + // printf("Qui ci arrivo\n"); double sommatoria = 0.0; - //printf("Layer %d: N_percettroni: %d\n", livello, rete.layers[livello].size); - //Calcolo la sommatoria dei gradienti dei percettroni per i pesi - for(int indice_percettrone = 0; indice_percettrone < rete.layers[livello].size; indice_percettrone++) { + // printf("Layer %d: N_percettroni: %d\n", livello, rete.layers[livello].size); + // Calcolo la sommatoria dei gradienti dei percettroni per i pesi + for (int indice_percettrone = 0; indice_percettrone < rete.layers[livello].size; indice_percettrone++) + { sommatoria += (gradienti[livello][indice_peso] * rete.layers[livello].percettroni[indice_percettrone].pesi[indice_peso]); } return sommatoria; } -void correggi_pesi_percettrone_double(Percettrone *p, int layer, double **input, double gradiente_percettrone) { +double **elabora_sigmoidi(ReteNeurale rete, Istanza istanza) +{ + // sigmoidi è un array bidimensionale, la prima dimensione identifica il layer, la seconda il percettrone nel layer + // sigmoidi[indice_layer][indice_percettrone] + double **sigmoidi = (double **)malloc(sizeof(double *) * rete.size); + double *inputs = (double *)malloc(sizeof(double *) * N_INPUTS); + for(int i = 0; i < N_INPUTS; i++) { + inputs[i] = (double)istanza.dati[i]; + } - for (int indice_peso = 0; indice_peso < p->size; indice_peso++) { - //Determino il gradiente del peso + sigmoidi[0] = (double *)malloc(sizeof(double) * rete.layers[0].size); + for(int indice_percettrone = 0; indice_percettrone < rete.layers[0].size; indice_percettrone ++) { + sigmoidi[0][indice_percettrone] = sigmoide(rete.layers[0].percettroni[indice_percettrone], inputs); + } + + for(int indice_layer = 1; indice_layer < rete.size; indice_layer ++) { + sigmoidi[indice_layer] = (double *)malloc(sizeof(double) * rete.layers[indice_layer].size); + for(int indice_percettrone = 0; indice_percettrone < rete.layers[indice_layer].size; indice_percettrone ++) { + sigmoidi[indice_layer][indice_percettrone] = sigmoide(rete.layers[indice_layer].percettroni[indice_percettrone], sigmoidi[indice_layer-1]); + } + } + + return sigmoidi; +} + + +/* + ################# CORREZIONI ################################ +*/ + + +void correggi_pesi_percettrone_double(Percettrone *p, int layer, double **input, double gradiente_percettrone) +{ + + for (int indice_peso = 0; indice_peso < p->size; indice_peso++) + { + // Determino il gradiente del peso double gradiente_peso = gradiente_percettrone * input[layer - 1][indice_peso]; - //Modifico il peso - p->pesi[indice_peso] -= (gradiente_peso * LRE); + // Modifico il peso + p->pesi[indice_peso] += (gradiente_peso * LRE); } - p->bias -= (gradiente_percettrone * LRE); + p->bias += (gradiente_percettrone * LRE); } -void correggi_pesi_percettrone_byte(Percettrone *p, Istanza input, double gradiente_percettrone, int indice_percettrone) { - for (int indice_peso = 0; indice_peso < p->size; indice_peso++) { - //Determino il gradiente del peso +void correggi_pesi_percettrone_byte(Percettrone *p, Istanza input, double gradiente_percettrone, int indice_percettrone) +{ + for (int indice_peso = 0; indice_peso < p->size; indice_peso++) + { + // Determino il gradiente del peso double gradiente_peso = gradiente_percettrone * (double)input.dati[indice_peso]; - - //Modifico il peso Qui si impalla perchè per qualche ragione arriva size elevatissimo - p->pesi[indice_peso] -= (gradiente_peso * LRE); + + // Modifico il peso Qui si impalla perchè per qualche ragione arriva size elevatissimo + p->pesi[indice_peso] += (gradiente_peso * LRE); } - - p->bias -= (gradiente_percettrone * LRE); + + p->bias += (gradiente_percettrone * LRE); } -//Una volta finito il ciclo delle epoche viene salvato lo stato della rete neurale -void salvaReteNeurale(const char *filename, ReteNeurale *rete) { + +/* + ################# IMPORT EXPORT ################################ +*/ +void salvaReteNeurale(const char *filename, ReteNeurale *rete) +{ FILE *file = fopen(filename, "wb"); - if (!file) { + if (!file) + { perror("Errore nell'apertura del file"); exit(EXIT_FAILURE); } @@ -301,12 +268,14 @@ void salvaReteNeurale(const char *filename, ReteNeurale *rete) { fwrite(&rete->size, sizeof(int), 1, file); // Scrivi ogni layer - for (int i = 0; i < rete->size; i++) { + for (int i = 0; i < rete->size; i++) + { Layer *layer = &rete->layers[i]; fwrite(&layer->size, sizeof(int), 1, file); // Scrivi ogni percettrone nel layer - for (int j = 0; j < layer->size; j++) { + for (int j = 0; j < layer->size; j++) + { Percettrone *perc = &layer->percettroni[j]; fwrite(&perc->size, sizeof(int), 1, file); fwrite(perc->pesi, sizeof(double), perc->size, file); @@ -317,17 +286,19 @@ void salvaReteNeurale(const char *filename, ReteNeurale *rete) { fclose(file); } -//Quando parte il programma carica lo stato della rete neurale dal file oppure inizializza una rete neurale con pesi random se il file non esiste -ReteNeurale *caricaReteNeurale(const char *filename) { +ReteNeurale *caricaReteNeurale(const char *filename) +{ FILE *file = fopen(filename, "rb"); - if (!file) { + if (!file) + { perror("Errore nell'apertura del file"); return NULL; } ReteNeurale *rete = malloc(sizeof(ReteNeurale)); - if (!rete) { + if (!rete) + { perror("Errore nell'allocazione della memoria"); return NULL; } @@ -335,27 +306,32 @@ ReteNeurale *caricaReteNeurale(const char *filename) { // Leggi il numero di layer fread(&rete->size, sizeof(int), 1, file); rete->layers = malloc(rete->size * sizeof(Layer)); - if (!rete->layers) { + if (!rete->layers) + { perror("Errore nell'allocazione della memoria"); return NULL; } // Leggi ogni layer - for (int i = 0; i < rete->size; i++) { + for (int i = 0; i < rete->size; i++) + { Layer *layer = &rete->layers[i]; fread(&layer->size, sizeof(int), 1, file); layer->percettroni = malloc(layer->size * sizeof(Percettrone)); - if (!layer->percettroni) { + if (!layer->percettroni) + { perror("Errore nell'allocazione della memoria"); return NULL; } // Leggi ogni percettrone nel layer - for (int j = 0; j < layer->size; j++) { + for (int j = 0; j < layer->size; j++) + { Percettrone *perc = &layer->percettroni[j]; fread(&perc->size, sizeof(int), 1, file); perc->pesi = malloc(perc->size * sizeof(double)); - if (!perc->pesi) { + if (!perc->pesi) + { perror("Errore nell'allocazione della memoria"); return NULL; } @@ -366,4 +342,130 @@ ReteNeurale *caricaReteNeurale(const char *filename) { fclose(file); return rete; -} \ No newline at end of file +} + + + + + + + + + +/* double sigmoide_byte(Percettrone, byte *, int); +double sigmoide_double(Percettrone, double *, int); +double *funzioni_attivazione_layer_byte(Layer, byte *); +double *funzioni_attivazione_layer_double(Layer, double *); */ +/* void correggi_layer_interni(ReteNeurale *, double **, double **); +void correggi_layer_input(Layer *, double **, double **, byte *, int); */ +/* // Questa funzione calcola tutte le funzioni di attivazione dei percettroni del layer che prende dei byte come inputs +double *funzioni_attivazione_layer_byte(Layer layer, byte *inputs) +{ + + double *funzioni = (double *)malloc(sizeof(double) * layer.size); + + for (int i = 0; i < layer.size; i++) + { + funzioni[i] = sigmoide_byte(layer.percettroni[i], inputs, layer.percettroni[i].size); + // printf("\tsigmoide layer input %f\n", funzioni[i]); + } + + return funzioni; +} + +// Questa funzione calcola tutte le funzioni di attivazione dei percettroni del layer che prende dei double come inputs (le sigmoidi del livello precedente) +double *funzioni_attivazione_layer_double(Layer layer, double *inputs) +{ + + double *funzioni = (double *)malloc(sizeof(double) * layer.size); + + for (int i = 0; i < layer.size; i++) + { + funzioni[i] = sigmoide_double(layer.percettroni[i], inputs, layer.percettroni[i].size); + // printf("\tsigmoide layer %d: %f\n", i, funzioni[i]); + } + + return funzioni; +} + */ +/* // Questa funzione prende la matrice dei gradienti e la matrice delle sigmoidi per correggere tutti i layer tranne quello di ingresso +void correggi_layer_interni(ReteNeurale *rete, double **gradienti, double **sigmoidi) +{ + + for (int indice_layer = rete->size - 1; indice_layer > 0; indice_layer--) + { + for (int indice_percettrone = 0; indice_percettrone < rete->layers[indice_layer].size; indice_percettrone++) + { // Numero percettroni + + for (int indice_peso = 0; indice_peso < rete->layers[indice_layer].percettroni[indice_percettrone].size; indice_peso++) + { // Numero pesi + gradienti[indice_layer][indice_percettrone] = gradienti[rete->size - 1][0] * (sigmoidi[indice_layer][indice_percettrone] * (1 - sigmoidi[indice_layer][indice_percettrone])); + rete->layers[indice_layer].percettroni[indice_percettrone].pesi[indice_peso] += (gradienti[indice_layer][indice_percettrone] * LRE * sigmoidi[indice_layer - 1][indice_percettrone]); + // rete->layers[indice_layer].percettroni[indice_percettrone].pesi[indice_peso] += (gradienti[rete->size-1][0] * LRE * sigmoidi[indice_layer-1][indice_percettrone]); + } + rete->layers[indice_layer].percettroni[indice_percettrone].bias += (gradienti[indice_layer][indice_percettrone] * LRE); + // printf("bias: %f\n", rete->layers[indice_layer].percettroni[indice_percettrone].bias); + } + } +} +// Questa funzione prende tutti i parametri della precedente + gli input passati dal dataset per correggere il layer di ingresso +void correggi_layer_input(Layer *layer, double **gradienti, double **sigmoidi, byte *inputs, int n_layers) +{ + // L'indice del layer d'ingresso che prende byte per input + int indice_layer = 0; + for (int indice_percettrone = 0; indice_percettrone < layer->size; indice_percettrone++) + { // Numero percettroni + for (int indice_peso = 0; indice_peso < layer->percettroni->size; indice_peso++) + { // Numero pesi + + gradienti[indice_layer][indice_percettrone] = gradienti[n_layers - 1][0] * (sigmoidi[indice_layer][indice_percettrone] * (1 - sigmoidi[indice_layer][indice_percettrone])); + layer->percettroni[indice_percettrone].pesi[indice_peso] += (gradienti[indice_layer][indice_percettrone] * LRE * inputs[indice_peso]); + // layer->percettroni[indice_percettrone].pesi[indice_peso] += (gradienti[n_layers-1][0] * LRE * inputs[indice_peso]); + } + layer->percettroni[indice_percettrone].bias += (gradienti[n_layers - 1][0] * LRE); + } +} + */ +/* +// Questa funzione viene usata per il primo livello perchè ha un vettore di byte (unsigned char) in input +double sigmoide_byte(Percettrone p, byte *valori, int n_input) +{ + + double sommatoria = 0.0; + // printf("valori: [%d][%d]", valori[0], valori[1]); + // printf("pesi: [%f][%f]", p.pesi[0], p.pesi[1]); + + for (int i = 0; i < n_input; i++) + { + sommatoria += ((double)valori[i] * p.pesi[i]); + } + // printf("sommatoria= %f\n", sommatoria); + double funzione = sommatoria + p.bias; + double potenza_e = exp(-funzione); + // printf("potenza_e= %f\n", potenza_e); + // formula sigmoide + double risultato = 1.0 / (1.0 + potenza_e); + // printf("risultato= %f\n", risultato); + return risultato; +} + +// Questa funzione viene usata per gli altri livelli dove gli input sono double, ossia i valori della sigmoide dei livelli precedenti +double sigmoide_double(Percettrone p, double *valori, int n_input) +{ + double sommatoria = 0.0; + for (int i = 0; i < n_input; i++) + { + sommatoria += (valori[i] * p.pesi[i]); + } + + double funzione = sommatoria + p.bias; + // printf("sommatoria= %f\n", sommatoria); + double potenza_e = exp(-funzione); + // printf("potenza_e= %f\n", potenza_e); + // formula sigmoide + double risultato = 1.0 / (1.0 + potenza_e); + // printf("risultato= %f\n", risultato); + + return risultato; +} + */ \ No newline at end of file diff --git a/xor_manager.h b/xor_manager.h index f525694..b5dcc68 100644 --- a/xor_manager.h +++ b/xor_manager.h @@ -29,19 +29,19 @@ Dataset *crea_dataset_xor() { set->istanze[0].dati[0] = 0; set->istanze[0].dati[1] = 0; - set->istanze[0].classificazione = 1; + set->istanze[0].classificazione = 0; set->istanze[1].dati[0] = 0; set->istanze[1].dati[1] = 1; - set->istanze[1].classificazione = 0; + set->istanze[1].classificazione = 1; set->istanze[2].dati[0] = 1; set->istanze[2].dati[1] = 0; - set->istanze[2].classificazione = 0; + set->istanze[2].classificazione = 1; set->istanze[3].dati[0] = 1; set->istanze[3].dati[1] = 1; - set->istanze[3].classificazione = 1; + set->istanze[3].classificazione = 0; return set; } \ No newline at end of file