Files
classificatore_immagini/rete_neurale.c

162 lines
6.8 KiB
C

#include <stdio.h>
#include <time.h>
#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;
}