pusho per testare nel threadripper
This commit is contained in:
@@ -8,4 +8,3 @@ frog
|
||||
horse
|
||||
ship
|
||||
truck
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<meta HTTP-EQUIV="REFRESH" content="0; url=http://www.cs.toronto.edu/~kriz/cifar.html">
|
||||
BIN
classificatore_singolo
Executable file
BIN
classificatore_singolo
Executable file
Binary file not shown.
124
classificatore_singolo.c
Normal file
124
classificatore_singolo.c
Normal file
@@ -0,0 +1,124 @@
|
||||
#include "visualizzatore.h"
|
||||
|
||||
#define NUM_LAYERS 5
|
||||
|
||||
#define PERCETTRONI_LAYER_0 256
|
||||
#define INPUT_LAYER_0 3072
|
||||
#define PERCETTRONI_LAYER_1 128
|
||||
#define INPUT_LAYER_1 256
|
||||
#define PERCETTRONI_LAYER_2 64
|
||||
#define INPUT_LAYER_2 128
|
||||
#define PERCETTRONI_LAYER_3 10
|
||||
#define INPUT_LAYER_3 64
|
||||
#define PERCETTRONI_LAYER_4 1
|
||||
#define INPUT_LAYER_4 10
|
||||
|
||||
#define MAX_EPOCHE 100
|
||||
|
||||
//Scelgo quale categoria voglio identificare. La 7 sono i cavalli. La rete mi dirà per ogni immagine se è un cavallo o no
|
||||
#define CATEGORIA 7
|
||||
byte get_out_corretto(byte);
|
||||
void stampa_layer_indirizzo(Layer*);
|
||||
|
||||
void main() {
|
||||
srand(time(NULL));
|
||||
|
||||
/* init_allegro();
|
||||
|
||||
// Carica la prima immagine
|
||||
load_current_image(set);
|
||||
|
||||
while (!key[KEY_ESC]) {
|
||||
draw_interface();
|
||||
handle_input(set);
|
||||
rest(10);
|
||||
}
|
||||
|
||||
destroy_bitmap(buffer);
|
||||
destroy_bitmap(image);
|
||||
allegro_exit(); */
|
||||
|
||||
Dataset *set_appoggio = get_dataset("cifar-10-batches/data_batch_1.bin");
|
||||
if(set_appoggio == NULL)
|
||||
return;
|
||||
Dataset set = *set_appoggio;
|
||||
free(set_appoggio);
|
||||
|
||||
ReteNeurale rete_neurale = inizializza_rete_neurale(NUM_LAYERS);
|
||||
//inizializzo layer 0
|
||||
rete_neurale.layers[0] = inizializza_layer(PERCETTRONI_LAYER_0, INPUT_LAYER_0);
|
||||
//inizializzo layer 1
|
||||
rete_neurale.layers[1] = inizializza_layer(PERCETTRONI_LAYER_1, INPUT_LAYER_1);
|
||||
//inizializzo layer 2
|
||||
rete_neurale.layers[2] = inizializza_layer(PERCETTRONI_LAYER_2, INPUT_LAYER_2);
|
||||
//inizializzo layer 3
|
||||
rete_neurale.layers[3] = inizializza_layer(PERCETTRONI_LAYER_3, INPUT_LAYER_3);
|
||||
//inizializzo layer ULTIMO
|
||||
rete_neurale.layers[4] = inizializza_layer(PERCETTRONI_LAYER_4, INPUT_LAYER_4);
|
||||
|
||||
printf("Numero immagini: %d\n",set.size);
|
||||
|
||||
//ADDESTRAMENTO
|
||||
for(int i = 0; i < MAX_EPOCHE; i++) {
|
||||
printf("Epoca %d\n", i);
|
||||
|
||||
int corrette = 0;
|
||||
|
||||
for(int indice_set = 0; indice_set < 100; indice_set++) {
|
||||
|
||||
//printf("\timmagine: %d\n", indice_set);
|
||||
|
||||
double **sigmoidi = (double **)malloc(sizeof(double*) * NUM_LAYERS);
|
||||
|
||||
sigmoidi[0] = (double*)malloc(sizeof(double) * PERCETTRONI_LAYER_0);
|
||||
sigmoidi[0] = funzioni_attivazione_layer_byte(rete_neurale.layers[0], set.istanze[indice_set].immagine);
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
byte output_corretto = get_out_corretto(set.istanze[indice_set].categoria);
|
||||
|
||||
//Se prevede male
|
||||
if(previsione(sigmoidi[NUM_LAYERS-1][0]) != output_corretto) {
|
||||
|
||||
double **gradienti = (double**)malloc(sizeof(double*) * NUM_LAYERS);
|
||||
|
||||
for(int indice_layer = 0; indice_layer < NUM_LAYERS; indice_layer++) {
|
||||
gradienti[indice_layer] = (double*)malloc(sizeof(double) * rete_neurale.layers[indice_layer].size);
|
||||
}
|
||||
|
||||
gradienti[NUM_LAYERS-1][0] = output_corretto - sigmoidi[NUM_LAYERS-1][0];
|
||||
|
||||
correggi_layer_interni(&rete_neurale, gradienti, sigmoidi);
|
||||
correggi_layer_input(&rete_neurale.layers[0], gradienti, sigmoidi, set.istanze[indice_set].immagine, NUM_LAYERS);
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf("immagine: %d categoria: %d, risposta_esatta: %d, previsione: %d\n", indice_set, set.istanze[indice_set].categoria, output_corretto, previsione(*sigmoide_out));
|
||||
corrette++;
|
||||
}
|
||||
}
|
||||
printf("\tRisposte corrette: %d\n", corrette);
|
||||
}
|
||||
}
|
||||
|
||||
//Questa funzione ritorna 1 se la categoria è quella che voglio individuare, altrimenti 0
|
||||
byte get_out_corretto(byte categoria) {
|
||||
if(categoria == CATEGORIA)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
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]);
|
||||
layer->percettroni[i].pesi[j] += 1;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
74
dataset_manager.h
Normal file
74
dataset_manager.h
Normal file
@@ -0,0 +1,74 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define N_PIXEL 3072 //1024 pixel * 3 (R, G, B)
|
||||
|
||||
//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;
|
||||
|
||||
// Singola istanza del dataset.
|
||||
typedef struct {
|
||||
byte categoria;
|
||||
byte immagine[N_PIXEL];
|
||||
} Istanza;
|
||||
|
||||
//Questo tipo fornisce il vettore delle istanze e il size (dimensione) del vettore
|
||||
typedef struct {
|
||||
int size;
|
||||
Istanza *istanze;
|
||||
} Dataset;
|
||||
|
||||
Dataset* get_dataset(char *);
|
||||
|
||||
//Questo metodo legge il file in questione e restituisce un puntatore a Dataset se il file esiste, altrimenti NULL
|
||||
//Ritorna un puntatore perchè in questo caso posso gestire il ritorno NULL.
|
||||
Dataset* get_dataset(char *path) {
|
||||
|
||||
Dataset *set = (Dataset *) malloc(sizeof(Dataset));
|
||||
FILE *file;
|
||||
Istanza istanza;
|
||||
Istanza *istanze = (Istanza *)malloc(sizeof(Istanza));
|
||||
|
||||
file = fopen(path, "rb");
|
||||
if(file == NULL)
|
||||
return NULL;
|
||||
|
||||
int numero_righe = 0;
|
||||
|
||||
//Fino a quando questo fread restituisce 1 significa che il file contiene ancora roba
|
||||
while(fread(&istanze[numero_righe].categoria, sizeof(byte), 1, file) == 1) {
|
||||
if(fread(istanze[numero_righe].immagine, sizeof(byte), N_PIXEL, file) == N_PIXEL) {
|
||||
numero_righe ++;
|
||||
istanze = (Istanza *)realloc(istanze, sizeof(Istanza) * (numero_righe + 1));
|
||||
//printf("Caricata nel sistema riga %d\n", numero_righe);
|
||||
}
|
||||
}
|
||||
|
||||
//Dataset set;
|
||||
(*set).size = numero_righe;
|
||||
(*set).istanze = istanze;
|
||||
|
||||
fclose(file);
|
||||
|
||||
return set;
|
||||
}
|
||||
|
||||
/* void main() {
|
||||
char *path = "cifar-10-batches/data_batch_1.bin";
|
||||
|
||||
//Carico il dataset e controllo che non sia nullo
|
||||
Dataset *dataset = get_dataset(path);
|
||||
if(dataset == NULL) {
|
||||
printf("Oggetto dataset nullo\n");
|
||||
return;
|
||||
}
|
||||
|
||||
//Lo copio in una seconda variabile per non dover mettere sempre * davanti al nome e libero la memoria occupata dal puntatore
|
||||
Dataset set = *dataset;
|
||||
free(dataset);
|
||||
|
||||
//Stampa di debug
|
||||
for(int i = 0; i < set.size; i++) {
|
||||
printf("n: %d. Categoria: %d\n", i, (int)set.istanze[i].categoria);
|
||||
}
|
||||
} */
|
||||
198
percettroni.h
198
percettroni.h
@@ -8,40 +8,108 @@
|
||||
In output ci sono 10 percettroni, ognuno di essi è associato ad una categoria del CIFAR10. Alla fine dell'addestramento, la previsione sarà
|
||||
data dal percettrone di output che avrà il valore 1 rispetto agli altri 9.
|
||||
*/
|
||||
#include<stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#define INPUT_LIV1 3072
|
||||
#define INPUT_LIV2 256
|
||||
#define INPUT_LIV3 128
|
||||
#include <math.h>
|
||||
#include "dataset_manager.h"
|
||||
|
||||
double LRE = 0.2;
|
||||
double soglia_sigmoide = 0.5;
|
||||
|
||||
typedef struct {
|
||||
double *pesi;
|
||||
double bias;
|
||||
double lre;
|
||||
int size;
|
||||
} Percettrone;
|
||||
|
||||
double randomico();
|
||||
void inzializza_percettrone(Percettrone*, int);
|
||||
double funzione_sigmoide(Percettrone, int[], int);
|
||||
typedef struct {
|
||||
Percettrone *percettroni;
|
||||
int size;
|
||||
} Layer;
|
||||
|
||||
typedef struct {
|
||||
Layer *layers;
|
||||
int size;
|
||||
} ReteNeurale;
|
||||
|
||||
double randomico();
|
||||
|
||||
Percettrone inzializza_percettrone(int);
|
||||
ReteNeurale inizializza_rete_neurale(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);
|
||||
|
||||
int previsione(double);
|
||||
|
||||
//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);
|
||||
}
|
||||
|
||||
void inizializza_percettrone(Percettrone *p, int n_pesi) {
|
||||
p->pesi = (double*)malloc(sizeof(double) * n_pesi );
|
||||
//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 p;
|
||||
p.pesi = (double*) malloc(sizeof(double) * n_pesi);
|
||||
for(int i = 0; i < n_pesi; i++)
|
||||
p->pesi[i] = randomico();
|
||||
p.pesi[i] = randomico();
|
||||
|
||||
p->bias = randomico();
|
||||
p->lre = LRE;
|
||||
p.bias = randomico();
|
||||
|
||||
p.size = n_pesi;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
double funzione_sigmoide(Percettrone p, int valori[], int n_input) {
|
||||
//Questa funzione inizializza una rete neurale. Diamo il numero di layer desiderato e restituisce un ReteNeurale
|
||||
ReteNeurale inizializza_rete_neurale(int n_layers) {
|
||||
ReteNeurale r;
|
||||
r.layers = (Layer*)malloc(sizeof(Layer) * n_layers);
|
||||
r.size = n_layers;
|
||||
|
||||
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 layer;
|
||||
layer.percettroni = (Percettrone *)malloc(sizeof(Percettrone) * n_percettroni);
|
||||
|
||||
for(int i = 0; i < n_percettroni; i++) {
|
||||
layer.percettroni[i] = inizializza_percettrone(n_pesi);
|
||||
}
|
||||
|
||||
layer.size = n_percettroni;
|
||||
|
||||
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;
|
||||
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 / ( 1 + 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++) {
|
||||
@@ -49,10 +117,106 @@ double funzione_sigmoide(Percettrone p, int valori[], int n_input) {
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
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]);
|
||||
|
||||
//if(indice_layer == 3)
|
||||
// printf("qui ci arrivo layer: %d, percettrone: %d, input:%d, peso: %f\n", indice_layer, indice_percettrone, indice_peso, rete->layers[indice_layer].percettroni[indice_percettrone].pesi[indice_peso]);
|
||||
|
||||
//printf("gradiente applicato %f, sigmoide %f\n", gradienti[indice_layer][indice_percettrone], sigmoidi[indice_layer][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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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].bias -= (gradienti[indice_layer][indice_percettrone] * LRE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* void correggi_pesi_layer(Percettrone[], int, int, double**, double[], double[]);
|
||||
void correggi_pesi_layer_uno(Percettrone[], int, int, double**, byte[], double[]);
|
||||
|
||||
void correggi_pesi_layer(Percettrone percettroni_layer[], int size_percettroni, int size_inputs, double **gradienti, double inputs[], double gradienti_bias[]) {
|
||||
for(int i = 0; i < size_percettroni; i++) {
|
||||
// Non termina questo for
|
||||
for(int j = 0; j < size_inputs; j++) {
|
||||
percettroni_layer[i].pesi[j] -= LRE * gradienti[i][j] * inputs[j];
|
||||
}
|
||||
percettroni_layer[i].bias -= LRE * gradienti_bias[i];
|
||||
}
|
||||
}
|
||||
|
||||
void correggi_pesi_layer_uno(Percettrone percettroni_layer[], int size_percettroni, int size_inputs, double **gradienti, byte inputs[], double gradienti_bias[]) {
|
||||
|
||||
for(int i = 0; i < size_percettroni; i++) {
|
||||
for(int j = 0; j < size_inputs; j++) {
|
||||
percettroni_layer[i].pesi[j] -= LRE * gradienti[i][j] * inputs[j];
|
||||
}
|
||||
percettroni_layer[i].bias -= LRE * gradienti_bias[i];
|
||||
}
|
||||
} */
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include "percettroni.h"
|
||||
|
||||
#define PERCETTRONI_1 256
|
||||
#define PERCETTRONI_2 128
|
||||
#define PERCETTRONI_OUT 10
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
rete_neurale
Executable file
BIN
rete_neurale
Executable file
Binary file not shown.
162
rete_neurale.c
Normal file
162
rete_neurale.c
Normal file
@@ -0,0 +1,162 @@
|
||||
#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;
|
||||
}
|
||||
1
tempCodeRunnerFile.c
Normal file
1
tempCodeRunnerFile.c
Normal file
@@ -0,0 +1 @@
|
||||
printf("qui ci arrivo else\n");
|
||||
BIN
visualizzatore
Executable file
BIN
visualizzatore
Executable file
Binary file not shown.
75
visualizzatore.h
Normal file
75
visualizzatore.h
Normal file
@@ -0,0 +1,75 @@
|
||||
#include <allegro.h>
|
||||
#include "percettroni.h"
|
||||
|
||||
#define IMAGE_WIDTH 32
|
||||
#define IMAGE_HEIGHT 32
|
||||
#define SCALE_FACTOR 2
|
||||
|
||||
BITMAP *buffer;
|
||||
BITMAP *image;
|
||||
|
||||
void init_allegro() {
|
||||
allegro_init();
|
||||
install_keyboard();
|
||||
install_mouse();
|
||||
set_color_depth(32);
|
||||
set_gfx_mode(GFX_AUTODETECT_WINDOWED, 800, 600, 0, 0);
|
||||
buffer = create_bitmap(800,600);
|
||||
image = create_bitmap(IMAGE_WIDTH, IMAGE_HEIGHT);
|
||||
show_mouse(screen);
|
||||
}
|
||||
|
||||
void load_current_image(Dataset *set) {
|
||||
int indice = rand()%set->size;
|
||||
for (int y = 0; y < IMAGE_HEIGHT; y++) {
|
||||
for (int x = 0; x < IMAGE_WIDTH; x++) {
|
||||
int r = set->istanze[indice].immagine[y * IMAGE_WIDTH + x];
|
||||
int g = set->istanze[indice].immagine[1024 + y * IMAGE_WIDTH + x];
|
||||
int b = set->istanze[indice].immagine[2048 + y * IMAGE_WIDTH + x];
|
||||
putpixel(image, x, y, makecol(r, g, b));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void draw_interface() {
|
||||
clear_to_color(buffer, makecol(255, 255, 255));
|
||||
|
||||
// Calcola la posizione per centrare l'immagine ingrandita
|
||||
int scaled_width = IMAGE_WIDTH * SCALE_FACTOR;
|
||||
int scaled_height = IMAGE_HEIGHT * SCALE_FACTOR;
|
||||
int image_x = (800 - scaled_width) / 2;
|
||||
int image_y = (600 - scaled_height) / 2 - 20; // Sposta leggermente sopra per fare spazio al pulsante
|
||||
|
||||
// Disegna l'immagine ingrandita
|
||||
stretch_blit(image, buffer, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, image_x, image_y, scaled_width, scaled_height);
|
||||
|
||||
// Disegna il pulsante "prossima"
|
||||
int button_width = 150;
|
||||
int button_height = 40;
|
||||
int button_x = (800 - button_width) / 2;
|
||||
int button_y = 600 - 60; // Posizione in basso
|
||||
rectfill(buffer, button_x, button_y, button_x + button_width, button_y + button_height, makecol(200, 200, 200));
|
||||
textout_centre_ex(buffer, font, "prossima", button_x + button_width / 2, button_y + 10, makecol(0, 0, 0), -1);
|
||||
|
||||
// Copia il buffer sullo schermo
|
||||
blit(buffer, screen, 0, 0, 0, 0, 800, 600);
|
||||
}
|
||||
|
||||
void handle_input(Dataset *set) {
|
||||
if (mouse_b & 1) {
|
||||
int mx = mouse_x;
|
||||
int my = mouse_y;
|
||||
|
||||
// Coordinate del pulsante
|
||||
int button_width = 150;
|
||||
int button_height = 40;
|
||||
int button_x = (800 - button_width) / 2;
|
||||
int button_y = 600 - 60;
|
||||
|
||||
// Controlla se il clic è avvenuto sul pulsante
|
||||
if (mx >= button_x && mx <= button_x + button_width && my >= button_y && my <= button_y + button_height) {
|
||||
load_current_image(set);
|
||||
rest(200); // Debounce
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user