#include #include #include "percettroni.h" #define PERCETTRONI_1 256 #define PERCETTRONI_2 128 #define PERCETTRONI_OUT 10 #define MAX_EPOCHE 1 double** alloca_memoria_bidimensionale(int, int); void main() { srand(time(NULL)); Percettrone livello_uno[PERCETTRONI_1]; Percettrone livello_due[PERCETTRONI_2]; Percettrone livello_out[PERCETTRONI_OUT]; for (int i = 0; i < PERCETTRONI_1; i++) { inizializza_percettrone(&livello_uno[i], INPUT_LIV1); if (i < PERCETTRONI_2) { inizializza_percettrone(&livello_due[i], INPUT_LIV2); if (i < PERCETTRONI_OUT) inizializza_percettrone(&livello_out[i], INPUT_LIV3); } } Dataset *set_appoggio = get_dataset("cifar-10-batches/data_batch_1.bin"); if (set_appoggio == NULL) return; Dataset dataset = *set_appoggio; free(set_appoggio); // Ciclo esterno per contare le epoche for (int indice_epoca = 0; indice_epoca < MAX_EPOCHE; indice_epoca++) { // Ciclo interno per contare tutte le istanze del dataset da analizzare nell'epoca corrente for (int indice_dataset = 0; indice_dataset < dataset.size; indice_dataset++) { // Qui memorizzo tutte le sigmoidi della rete double sigmoidi_livello_uno[PERCETTRONI_1]; double sigmoidi_livello_due[PERCETTRONI_2]; double sigmoidi_livello_out[PERCETTRONI_OUT]; // Livello 1 // Ho 256 percettroni da riempire for (int i = 0; i < PERCETTRONI_1; i++) sigmoidi_livello_uno[i] = funzione_sigmoide_primo_livello(livello_uno[i], dataset.istanze[indice_dataset].immagine, INPUT_LIV1); // Livello 2 // Ho 128 percettroni da riempire for (int i = 0; i < PERCETTRONI_2; i++) sigmoidi_livello_due[i] = funzione_sigmoide(livello_due[i], sigmoidi_livello_uno, INPUT_LIV2); // Livello OUT // Ho 10 percettroni da riempire for (int i = 0; i < PERCETTRONI_OUT; i++) { sigmoidi_livello_out[i] = funzione_sigmoide(livello_out[i], sigmoidi_livello_due, INPUT_LIV3); printf("Sigmoide %d: %f\n", i, sigmoidi_livello_out[i]); } // Determinare l'errore e la previsione // Ho 10 percettroni in uscita, la previsione è che uno sarà 1 mentre tutti gli altri 0. // Il percettrone con 1 è quello di indice dataset.istanze[indice_dataset].categoria int indice_corretto = dataset.istanze[indice_dataset].categoria; double errori[PERCETTRONI_OUT]; printf("Fino a qui ci arrivo 1\n"); double **gradienti_out = alloca_memoria_bidimensionale(PERCETTRONI_OUT, INPUT_LIV3); double gradienti_bias_out[PERCETTRONI_OUT]; double **gradienti_2 = alloca_memoria_bidimensionale(PERCETTRONI_2, INPUT_LIV2); double gradienti_bias_2[PERCETTRONI_2]; double **gradienti_1 = alloca_memoria_bidimensionale(PERCETTRONI_1, INPUT_LIV1); double gradienti_bias_1[PERCETTRONI_1]; // Per ogni percettrone di uscita vedo se ha commesso errore e mi calcolo il gradiente for (int i = 0; i < PERCETTRONI_OUT; i++) { // Se la i corrisponde all'indice corretto, la previsione dovrebbe essere 1, se non lo è c'è errore if (i == indice_corretto) { if (prevedi(sigmoidi_livello_out[i]) != 1) { // Errore errori[i] = 1 - sigmoidi_livello_out[i]; for (int j = 0; j < INPUT_LIV3; j++) gradienti_out[i][j] = errori[i] * sigmoidi_livello_out[i] * (1 - sigmoidi_livello_out[i]) /* * sigmoidi_livello_due[j] */; gradienti_bias_out[i] = errori[i] * sigmoidi_livello_out[i] * (1 - sigmoidi_livello_out[i]); //Qui potrei moltiplicarmi i pesi per i gradienti quindi correggere il livello output for (int j = 0; j < PERCETTRONI_2; j++) { for (int k = 0; k < INPUT_LIV2; k++) gradienti_2[j][k] = gradienti_out[i][j] * sigmoidi_livello_due[j] * (1 - sigmoidi_livello_due[j]); gradienti_bias_2[j] = gradienti_out[i][j] * sigmoidi_livello_due[j] * (1 - sigmoidi_livello_due[j]); //Qui potrei moltiplicarmi i pesi per i gradienti quindi correggere il livello due for (int y = 0; y < PERCETTRONI_1; y++) { for (int z = 0; z < INPUT_LIV1; z++) gradienti_1[y][z] = gradienti_out[i][j] * gradienti_2[j][y] * sigmoidi_livello_uno[y] * (1 - sigmoidi_livello_uno[y]); gradienti_bias_1[y] = gradienti_out[i][j] * gradienti_2[j][y] * sigmoidi_livello_uno[y] * (1 - sigmoidi_livello_uno[y]); //Qui potrei moltiplicarmi i pesi per i gradienti quindi correggere il livello uno } } } } else { // Qui determino quando deve valere zero } } printf("Fino a qui ci arrivo 2\n"); /* Devo dichiarare i gradienti col malloc */ correggi_pesi_layer(livello_out, PERCETTRONI_OUT, INPUT_LIV3, gradienti_out, sigmoidi_livello_due, gradienti_bias_out); printf("Fino a qui ci arrivo 3\n"); correggi_pesi_layer(livello_due, PERCETTRONI_2, INPUT_LIV2, gradienti_2, sigmoidi_livello_uno, gradienti_bias_2); printf("Fino a qui ci arrivo 4\n"); correggi_pesi_layer_uno(livello_uno, PERCETTRONI_1, INPUT_LIV1, gradienti_1, dataset.istanze[indice_dataset].immagine, gradienti_bias_1); printf("Fino a qui ci arrivo 5\n"); } } // Stampa di debug /* for(int i = 0; i < PERCETTRONI_1; i++) { printf("\nPercettrone esterno %d: w78: %f, bias: %f",i, livello_uno[i].pesi[77], livello_uno[i].bias); if(i < PERCETTRONI_2) { printf("\n\tPercettrone interno %d: w78: %f, bias: %f", i, livello_due[i].pesi[77], livello_due[i].bias); if(i < PERCETTRONI_OUT) printf("\n\t\tPercettrone output %d: w78: %f, bias: %f", i, livello_out[i].pesi[77], livello_out[i].bias); } }*/ printf("\r"); } double** alloca_memoria_bidimensionale(int x, int y) { double **vettore = (double **)malloc(sizeof(double*) * x); for(int i = 0; i < x; i++) vettore[i] = (double *)malloc(sizeof(double) * y); return vettore; }