162 lines
6.8 KiB
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;
|
|
} |