messo due codici da deepseek, per classificare il singolo e il multi classe

This commit is contained in:
2025-02-25 12:03:21 +01:00
parent 077952260a
commit 3876c7c5b5
9 changed files with 619 additions and 216 deletions

304
deep_seek.c Normal file
View File

@@ -0,0 +1,304 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include "cifar-10/cifar10_manager.h"
// Costanti configurabili
#define N_LAYERS 3 // Numero di layer (input, hidden, output)
#define N_NEURONI_HIDDEN 128 // Numero di neuroni nei layer nascosti
#define N_NEURONI_OUTPUT 10 // Numero di neuroni nel layer di output (10 classi)
#define N_EPOCHE 10 // Numero di epoche di addestramento
#define LEARNING_RATE 0.01 // Tasso di apprendimento
#define N_INPUTS 3072 // Dimensioni di un'immagine CIFAR-10 (32x32x3)
// Strutture dati
/* typedef unsigned char byte;
typedef struct {
byte classificazione;
byte dati[N_INPUTS];
} Istanza;
typedef struct {
int size;
Istanza *istanze;
} Dataset; */
typedef struct {
double *pesi;
double bias;
int size;
} Percettrone;
typedef struct {
Percettrone *percettroni;
int size;
} Layer;
typedef struct {
Layer *layers;
int size;
} ReteNeurale;
double sigmoide(double);
double relu(double);
double relu_derivata(double);
double softmax(double*, int, int);
ReteNeurale crea_rete();
double *prevedi(ReteNeurale*, byte*);
void allena(ReteNeurale*, Dataset*);
void salva_rete(ReteNeurale*, const char*);
ReteNeurale carica_rete(const char*);
void carica_immagini_casuali(Dataset*, byte[][N_INPUTS], byte*);
void fai_previsioni(ReteNeurale*, byte[][N_INPUTS], byte*);
void backpropagation(ReteNeurale*, byte*, byte, double*);
double *forward_pass(ReteNeurale*, byte*);
// Funzioni di utilità
double sigmoide(double x) {
return 1.0 / (1.0 + exp(-x));
}
double relu(double x) {
return x > 0 ? x : 0;
}
double relu_derivata(double x) {
return x > 0 ? 1 : 0;
}
double softmax(double *x, int index, int size) {
double max = x[0];
for (int i = 1; i < size; i++) {
if (x[i] > max) max = x[i];
}
double sum = 0.0;
for (int i = 0; i < size; i++) {
sum += exp(x[i] - max);
}
return exp(x[index] - max) / sum;
}
// Inizializzazione della rete
ReteNeurale crea_rete() {
ReteNeurale rete;
rete.size = N_LAYERS;
rete.layers = (Layer *)malloc(N_LAYERS * sizeof(Layer));
// Layer di input (non ha pesi, solo pass-through)
rete.layers[0].size = N_INPUTS;
rete.layers[0].percettroni = NULL;
// Layer nascosto
rete.layers[1].size = N_NEURONI_HIDDEN;
rete.layers[1].percettroni = (Percettrone *)malloc(N_NEURONI_HIDDEN * sizeof(Percettrone));
for (int i = 0; i < N_NEURONI_HIDDEN; i++) {
rete.layers[1].percettroni[i].size = N_INPUTS;
rete.layers[1].percettroni[i].pesi = (double *)malloc(N_INPUTS * sizeof(double));
for (int j = 0; j < N_INPUTS; j++) {
rete.layers[1].percettroni[i].pesi[j] = ((double)rand() / RAND_MAX) * 2 - 1; // Pesi casuali tra -1 e 1
}
rete.layers[1].percettroni[i].bias = ((double)rand() / RAND_MAX) * 2 - 1; // Bias casuale tra -1 e 1
}
// Layer di output
rete.layers[2].size = N_NEURONI_OUTPUT;
rete.layers[2].percettroni = (Percettrone *)malloc(N_NEURONI_OUTPUT * sizeof(Percettrone));
for (int i = 0; i < N_NEURONI_OUTPUT; i++) {
rete.layers[2].percettroni[i].size = N_NEURONI_HIDDEN;
rete.layers[2].percettroni[i].pesi = (double *)malloc(N_NEURONI_HIDDEN * sizeof(double));
for (int j = 0; j < N_NEURONI_HIDDEN; j++) {
rete.layers[2].percettroni[i].pesi[j] = ((double)rand() / RAND_MAX) * 2 - 1; // Pesi casuali tra -1 e 1
}
rete.layers[2].percettroni[i].bias = ((double)rand() / RAND_MAX) * 2 - 1; // Bias casuale tra -1 e 1
}
return rete;
}
// Funzione per la previsione
double *prevedi(ReteNeurale *rete, byte *input) {
double *output = (double *)malloc(N_NEURONI_OUTPUT * sizeof(double));
// Implementazione del forward pass
// (Da completare)
return output;
}
// Funzione per l'addestramento
void allena(ReteNeurale *rete, Dataset *dataset) {
printf("Sono dentro l'allenamento\n");
for (int epoca = 0; epoca < N_EPOCHE; epoca++) {
printf("Epoca %d\n", epoca);
for (int i = 0; i < dataset->size; i++) {
byte *input = dataset->istanze[i].dati;
byte target = dataset->istanze[i].classificazione;
// Forward pass
double *output_final = forward_pass(rete, input);
// Backpropagation
backpropagation(rete, input, target, output_final);
free(output_final);
}
}
}
// Forward pass
double *forward_pass(ReteNeurale *rete, byte *input) {
double *output_hidden = (double *)malloc(N_NEURONI_HIDDEN * sizeof(double));
double *output_final = (double *)malloc(N_NEURONI_OUTPUT * sizeof(double));
// Layer nascosto
for (int i = 0; i < N_NEURONI_HIDDEN; i++) {
double somma = 0.0;
for (int j = 0; j < N_INPUTS; j++) {
somma += input[j] * rete->layers[1].percettroni[i].pesi[j];
}
somma += rete->layers[1].percettroni[i].bias;
output_hidden[i] = relu(somma); // Applica ReLU
}
// Layer di output
for (int i = 0; i < N_NEURONI_OUTPUT; i++) {
double somma = 0.0;
for (int j = 0; j < N_NEURONI_HIDDEN; j++) {
somma += output_hidden[j] * rete->layers[2].percettroni[i].pesi[j];
}
somma += rete->layers[2].percettroni[i].bias;
output_final[i] = somma; // Non applica softmax qui, verrà fatto durante la loss
}
free(output_hidden);
return output_final;
}
// Backpropagation
void backpropagation(ReteNeurale *rete, byte *input, byte target, double *output_final) {
// Calcola la softmax e la loss (cross-entropy)
double softmax_output[N_NEURONI_OUTPUT];
double sum_exp = 0.0;
for (int i = 0; i < N_NEURONI_OUTPUT; i++) {
sum_exp += exp(output_final[i]);
}
for (int i = 0; i < N_NEURONI_OUTPUT; i++) {
softmax_output[i] = exp(output_final[i]) / sum_exp;
}
// Gradiente della loss rispetto all'output
double grad_output[N_NEURONI_OUTPUT];
for (int i = 0; i < N_NEURONI_OUTPUT; i++) {
grad_output[i] = softmax_output[i] - (i == target ? 1 : 0);
}
// Gradiente rispetto ai pesi e bias del layer di output
for (int i = 0; i < N_NEURONI_OUTPUT; i++) {
for (int j = 0; j < N_NEURONI_HIDDEN; j++) {
rete->layers[2].percettroni[i].pesi[j] -= LEARNING_RATE * grad_output[i] * output_final[j];
}
rete->layers[2].percettroni[i].bias -= LEARNING_RATE * grad_output[i];
}
// Gradiente rispetto ai pesi e bias del layer nascosto
double grad_hidden[N_NEURONI_HIDDEN];
for (int j = 0; j < N_NEURONI_HIDDEN; j++) {
grad_hidden[j] = 0.0;
for (int i = 0; i < N_NEURONI_OUTPUT; i++) {
grad_hidden[j] += grad_output[i] * rete->layers[2].percettroni[i].pesi[j];
}
grad_hidden[j] *= relu_derivata(output_final[j]); // Derivata di ReLU
}
for (int j = 0; j < N_NEURONI_HIDDEN; j++) {
for (int k = 0; k < N_INPUTS; k++) {
rete->layers[1].percettroni[j].pesi[k] -= LEARNING_RATE * grad_hidden[j] * input[k];
}
rete->layers[1].percettroni[j].bias -= LEARNING_RATE * grad_hidden[j];
}
}
// Serializzazione della rete
void salva_rete(ReteNeurale *rete, const char *filename) {
FILE *file = fopen(filename, "wb");
if (file == NULL) {
perror("Errore nell'apertura del file");
return;
}
fwrite(rete, sizeof(ReteNeurale), 1, file);
fclose(file);
}
// Deserializzazione della rete
ReteNeurale carica_rete(const char *filename) {
FILE *file = fopen(filename, "rb");
if (file == NULL) {
perror("Errore nell'apertura del file");
exit(1);
}
ReteNeurale rete;
fread(&rete, sizeof(ReteNeurale), 1, file);
fclose(file);
return rete;
}
// Funzione per caricare 4 immagini casuali dal dataset
void carica_immagini_casuali(Dataset *dataset, byte immagini[4][N_INPUTS], byte *etichette) {
for (int i = 0; i < 4; i++) {
int indice_casuale = rand() % dataset->size; // Sceglie un'immagine casuale
for (int j = 0; j < N_INPUTS; j++) {
immagini[i][j] = dataset->istanze[indice_casuale].dati[j]; // Copia i dati dell'immagine
}
etichette[i] = dataset->istanze[indice_casuale].classificazione; // Copia l'etichetta
}
}
// Funzione per fare previsioni su 4 immagini
void fai_previsioni(ReteNeurale *rete, byte immagini[4][N_INPUTS], byte *etichette) {
for (int i = 0; i < 4; i++) {
double *output = prevedi(rete, immagini[i]); // Passa l'immagine attraverso la rete
int previsione = 0;
double max_prob = output[0];
for (int j = 1; j < N_NEURONI_OUTPUT; j++) {
if (output[j] > max_prob) {
max_prob = output[j];
previsione = j;
}
}
printf("Immagine %d: Etichetta vera = %d, Previsione = %d\n", i + 1, etichette[i], previsione);
free(output); // Libera la memoria allocata per l'output
}
}
int main() {
srand(time(NULL));
printf("Mi appresto a caricare la rete\n");
// Creazione della rete
ReteNeurale rete = crea_rete();
printf("Mi appresto a caricare il dataset\n");
// Caricamento del dataset (da implementare)
Dataset *dataset;
dataset = get_dataset("cifar-10/data_batch_1.bin");
printf("Mi appresto ad allenare\n");
// Addestramento della rete
allena(&rete, dataset);
// Salvataggio della rete
salva_rete(&rete, "rete_neurale.bin");
// Caricamento di 4 immagini casuali
byte immagini[4][N_INPUTS];
byte etichette[4];
carica_immagini_casuali(dataset, immagini, etichette);
// Previsioni sulle immagini
fai_previsioni(&rete, immagini, etichette);
// Liberazione della memoria
// (Da implementare)
return 0;
}