Versione finale con grafico e legenda
This commit is contained in:
238
grafico.h
Normal file
238
grafico.h
Normal file
@@ -0,0 +1,238 @@
|
|||||||
|
#include <allegro.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
// Segmento che parte dalle coordinate x,y di "inizio" a quelle di "fine"
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
double m;
|
||||||
|
double q;
|
||||||
|
} Retta;
|
||||||
|
|
||||||
|
void disegna_assi();
|
||||||
|
void cls(int, int);
|
||||||
|
void disegna_punti(int);
|
||||||
|
void traccia_retta(double, double, int);
|
||||||
|
int *coordinate(int, int);
|
||||||
|
void stampa_epoca(int);
|
||||||
|
|
||||||
|
/* void main() {
|
||||||
|
allegro_init();
|
||||||
|
install_keyboard(); // Installa il gestore della tastiera
|
||||||
|
set_gfx_mode(GFX_AUTODETECT_WINDOWED, 800, 600, 0, 0);
|
||||||
|
cls();
|
||||||
|
|
||||||
|
for (int i = 0; i < 1000; i++) {
|
||||||
|
double m = (double)i / 100;
|
||||||
|
cls();
|
||||||
|
traccia_retta(m,1.5);
|
||||||
|
sleep(0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
readkey();
|
||||||
|
} */
|
||||||
|
|
||||||
|
/*
|
||||||
|
Schermo 800x600
|
||||||
|
Centro 400x300
|
||||||
|
|
||||||
|
0,0 - 400,0 - 800,0
|
||||||
|
0,300 - 400,300 - 800,300
|
||||||
|
0,600 - 400,600 - 800,600
|
||||||
|
|
||||||
|
Ogni punto nel grafico, 100 pixel
|
||||||
|
Range -2, 2
|
||||||
|
|
||||||
|
es retta y = mx + q con x=1, m=1, q=1
|
||||||
|
y = 1 * 1 + 1 = 2
|
||||||
|
|
||||||
|
x = 1
|
||||||
|
y = 2
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
void traccia_retta(double m, double q, int colore)
|
||||||
|
{
|
||||||
|
// determino il centro
|
||||||
|
int center_x = SCREEN_W / 2; // Coordinata x del centro
|
||||||
|
int center_y = SCREEN_H / 2; // Coordinata y del centro
|
||||||
|
|
||||||
|
// Retta coi valori reali
|
||||||
|
double x_start = -3;
|
||||||
|
double x_end = 3;
|
||||||
|
double y_start = (m * x_start + q);
|
||||||
|
double y_end = (m * x_end + q);
|
||||||
|
|
||||||
|
line(screen, center_x + (int)(x_start * 100), center_y - (int)(y_start * 100), center_x + (int)(x_end * 100), center_y - (int)(y_end * 100), colore);
|
||||||
|
sleep(0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void disegna_assi()
|
||||||
|
{
|
||||||
|
// determino il centro
|
||||||
|
int center_x = SCREEN_W / 2; // Coordinata x del centro
|
||||||
|
int center_y = SCREEN_H / 2; // Coordinata y del centro
|
||||||
|
|
||||||
|
// Colore delle linee
|
||||||
|
int colore_nero = makecol(0, 0, 0);
|
||||||
|
|
||||||
|
// Disegna gli assi
|
||||||
|
line(screen, center_x, 0, center_x, SCREEN_H - 1, colore_nero);
|
||||||
|
line(screen, 0, center_y, SCREEN_W - 1, center_y, colore_nero);
|
||||||
|
|
||||||
|
// Zero nel punto di intersezione
|
||||||
|
textout_ex(screen, font, "0", center_x - 10, center_y + 5, colore_nero, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void disegna_legenda(int multi_layer) {
|
||||||
|
|
||||||
|
int colore_rosso = makecol(255, 0, 0);
|
||||||
|
int colore_verde = makecol(0, 255, 0);
|
||||||
|
int colore_blu = makecol(0, 0, 255);
|
||||||
|
|
||||||
|
if(multi_layer == 0)
|
||||||
|
textout_ex(screen, font, "Percettrone", 0 + 10, 0 + 10, colore_rosso, -1);
|
||||||
|
else {
|
||||||
|
textout_ex(screen, font, "Percettrone 1", 0 + 10, 0 + 10, colore_rosso, -1);
|
||||||
|
textout_ex(screen, font, "Percettrone 2", 0 + 10, 0 + 20, colore_verde, -1);
|
||||||
|
textout_ex(screen, font, "Percettrone out", 0 + 10, 0 + 30, colore_blu, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void stampa_epoca(int epoca) {
|
||||||
|
int colore_rosso = makecol(255, 0, 0);
|
||||||
|
|
||||||
|
char stringa[4];
|
||||||
|
sprintf(stringa, "%d", epoca);
|
||||||
|
|
||||||
|
textout_ex(screen, font, stringa, SCREEN_W - 50, 0 + 20, colore_rosso, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
il tipo indica quali punti vogliamo disegnare nel grafico:
|
||||||
|
0: AND
|
||||||
|
1: OR
|
||||||
|
2: XOR
|
||||||
|
3: NAND
|
||||||
|
4: NOR
|
||||||
|
5: XNOR
|
||||||
|
*/
|
||||||
|
void cls(int tipo, int multi_layer)
|
||||||
|
{
|
||||||
|
clear_to_color(screen, makecol(255, 255, 255)); // Sfondo bianco
|
||||||
|
disegna_assi();
|
||||||
|
disegna_punti(tipo);
|
||||||
|
disegna_legenda(multi_layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void disegna_punti(int tipo)
|
||||||
|
{
|
||||||
|
int raggio = 3;
|
||||||
|
int colore_verde = makecol(0, 255, 0);
|
||||||
|
int colore_rosso = makecol(255, 0, 0);
|
||||||
|
int colore_nero = makecol(0, 0, 0);
|
||||||
|
|
||||||
|
textout_ex(screen, font, "Epoca:", SCREEN_W - 100, 0 + 20, colore_rosso, -1);
|
||||||
|
|
||||||
|
switch (tipo)
|
||||||
|
{
|
||||||
|
case 0: //AND
|
||||||
|
int *punto = coordinate(0, 0);
|
||||||
|
circlefill(screen, punto[0], punto[1], raggio, colore_rosso);
|
||||||
|
punto = coordinate(0, 1);
|
||||||
|
circlefill(screen, punto[0], punto[1], raggio, colore_rosso);
|
||||||
|
punto = coordinate(1, 0);
|
||||||
|
circlefill(screen, punto[0], punto[1], raggio, colore_rosso);
|
||||||
|
punto = coordinate(1, 1);
|
||||||
|
circlefill(screen, punto[0], punto[1], raggio, colore_verde);
|
||||||
|
|
||||||
|
textout_ex(screen, font, "AND", SCREEN_W - 50, 0 + 10, colore_nero, -1);
|
||||||
|
break;
|
||||||
|
case 1: //OR
|
||||||
|
punto = coordinate(0, 0);
|
||||||
|
circlefill(screen, punto[0], punto[1], raggio, colore_rosso);
|
||||||
|
punto = coordinate(0, 1);
|
||||||
|
circlefill(screen, punto[0], punto[1], raggio, colore_verde);
|
||||||
|
punto = coordinate(1, 0);
|
||||||
|
circlefill(screen, punto[0], punto[1], raggio, colore_verde);
|
||||||
|
punto = coordinate(1, 1);
|
||||||
|
circlefill(screen, punto[0], punto[1], raggio, colore_verde);
|
||||||
|
|
||||||
|
textout_ex(screen, font, "OR", SCREEN_W - 50, 0 + 10, colore_nero, -1);
|
||||||
|
break;
|
||||||
|
case 2: //XOR
|
||||||
|
punto = coordinate(0, 0);
|
||||||
|
circlefill(screen, punto[0], punto[1], raggio, colore_rosso);
|
||||||
|
punto = coordinate(0, 1);
|
||||||
|
circlefill(screen, punto[0], punto[1], raggio, colore_verde);
|
||||||
|
punto = coordinate(1, 0);
|
||||||
|
circlefill(screen, punto[0], punto[1], raggio, colore_verde);
|
||||||
|
punto = coordinate(1, 1);
|
||||||
|
circlefill(screen, punto[0], punto[1], raggio, colore_rosso);
|
||||||
|
|
||||||
|
textout_ex(screen, font, "XOR", SCREEN_W - 50, 0 + 10, colore_nero, -1);
|
||||||
|
break;
|
||||||
|
case 3: //NAND
|
||||||
|
punto = coordinate(0, 0);
|
||||||
|
circlefill(screen, punto[0], punto[1], raggio, colore_verde);
|
||||||
|
punto = coordinate(0, 1);
|
||||||
|
circlefill(screen, punto[0], punto[1], raggio, colore_verde);
|
||||||
|
punto = coordinate(1, 0);
|
||||||
|
circlefill(screen, punto[0], punto[1], raggio, colore_verde);
|
||||||
|
punto = coordinate(1, 1);
|
||||||
|
circlefill(screen, punto[0], punto[1], raggio, colore_rosso);
|
||||||
|
|
||||||
|
textout_ex(screen, font, "NAND", SCREEN_W - 50, 0 + 10, colore_nero, -1);
|
||||||
|
break;
|
||||||
|
case 4: //NOR
|
||||||
|
punto = coordinate(0, 0);
|
||||||
|
circlefill(screen, punto[0], punto[1], raggio, colore_verde);
|
||||||
|
punto = coordinate(0, 1);
|
||||||
|
circlefill(screen, punto[0], punto[1], raggio, colore_rosso);
|
||||||
|
punto = coordinate(1, 0);
|
||||||
|
circlefill(screen, punto[0], punto[1], raggio, colore_rosso);
|
||||||
|
punto = coordinate(1, 1);
|
||||||
|
circlefill(screen, punto[0], punto[1], raggio, colore_rosso);
|
||||||
|
|
||||||
|
textout_ex(screen, font, "NOR", SCREEN_W - 50, 0 + 10, colore_nero, -1);
|
||||||
|
break;
|
||||||
|
case 5: //XNOR
|
||||||
|
punto = coordinate(0, 0);
|
||||||
|
circlefill(screen, punto[0], punto[1], raggio, colore_verde);
|
||||||
|
punto = coordinate(0, 1);
|
||||||
|
circlefill(screen, punto[0], punto[1], raggio, colore_rosso);
|
||||||
|
punto = coordinate(1, 0);
|
||||||
|
circlefill(screen, punto[0], punto[1], raggio, colore_rosso);
|
||||||
|
punto = coordinate(1, 1);
|
||||||
|
circlefill(screen, punto[0], punto[1], raggio, colore_verde);
|
||||||
|
|
||||||
|
textout_ex(screen, font, "XNOR", SCREEN_W - 50, 0 + 10, colore_nero, -1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mi da le coordinate in pixel dati i punti in ingresso
|
||||||
|
int *coordinate(int x, int y)
|
||||||
|
{
|
||||||
|
// determino il centro
|
||||||
|
int center_x = SCREEN_W / 2; // Coordinata x del centro
|
||||||
|
int center_y = SCREEN_H / 2; // Coordinata y del centro
|
||||||
|
|
||||||
|
int *coordinate = (int *)malloc(sizeof(int) * 2);
|
||||||
|
|
||||||
|
coordinate[0] = center_x + (x * 100);
|
||||||
|
coordinate[1] = center_y - (y * 100);
|
||||||
|
|
||||||
|
return coordinate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sleep_ms(int milliseconds)
|
||||||
|
{
|
||||||
|
struct timespec ts;
|
||||||
|
ts.tv_sec = milliseconds / 1000;
|
||||||
|
ts.tv_nsec = (milliseconds % 1000) * 1000000;
|
||||||
|
nanosleep(&ts, NULL);
|
||||||
|
}
|
||||||
189
layer_multi.c
Normal file
189
layer_multi.c
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include "percettrone.h"
|
||||||
|
#include "grafico.h"
|
||||||
|
|
||||||
|
int MAX_EPOCHE = 10000;
|
||||||
|
|
||||||
|
/*
|
||||||
|
il tipo indica quali punti vogliamo disegnare nel grafico:
|
||||||
|
0: AND
|
||||||
|
1: OR
|
||||||
|
2: XOR
|
||||||
|
3: NAND
|
||||||
|
4: NOR
|
||||||
|
5: XNOR
|
||||||
|
*/
|
||||||
|
int tipo = 2;
|
||||||
|
|
||||||
|
void stampa_risultati(Percettrone);
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
srand(time(NULL));
|
||||||
|
|
||||||
|
allegro_init();
|
||||||
|
install_keyboard();
|
||||||
|
set_gfx_mode(GFX_AUTODETECT_WINDOWED, 800, 600, 0, 0);
|
||||||
|
cls(tipo, 1);
|
||||||
|
|
||||||
|
int output[4];
|
||||||
|
switch (tipo)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
output[0] = 0;
|
||||||
|
output[1] = 0;
|
||||||
|
output[2] = 0;
|
||||||
|
output[3] = 1;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
output[0] = 0;
|
||||||
|
output[1] = 1;
|
||||||
|
output[2] = 1;
|
||||||
|
output[3] = 1;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
output[0] = 0;
|
||||||
|
output[1] = 1;
|
||||||
|
output[2] = 1;
|
||||||
|
output[3] = 0;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
output[0] = 1;
|
||||||
|
output[1] = 1;
|
||||||
|
output[2] = 1;
|
||||||
|
output[3] = 0;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
output[0] = 1;
|
||||||
|
output[1] = 0;
|
||||||
|
output[2] = 0;
|
||||||
|
output[3] = 0;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
output[0] = 1;
|
||||||
|
output[1] = 0;
|
||||||
|
output[2] = 0;
|
||||||
|
output[3] = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Percettrone p_ext_1 = crea_percettrone();
|
||||||
|
int colore_rosso = makecol(255, 0, 0);
|
||||||
|
|
||||||
|
Percettrone p_ext_2 = crea_percettrone();
|
||||||
|
int colore_verde = makecol(0, 255, 0);
|
||||||
|
|
||||||
|
Percettrone pout = crea_percettrone();
|
||||||
|
int colore_blu = makecol(0, 0, 255);
|
||||||
|
|
||||||
|
// Contatore per fermare il percettrone, se vale 4 significa che ha indovinato tutte e 4 le combinazioni
|
||||||
|
int corrette = 0;
|
||||||
|
|
||||||
|
Retta *rette_p_ext_1 = (Retta *)malloc(sizeof(Retta));
|
||||||
|
Retta *rette_p_ext_2 = (Retta *)malloc(sizeof(Retta));
|
||||||
|
Retta *rette_pout = (Retta *)malloc(sizeof(Retta));
|
||||||
|
|
||||||
|
int size_iniziale = sizeof(rette_p_ext_1);
|
||||||
|
|
||||||
|
// Soglia sigmoide
|
||||||
|
double soglia_funzione_attivazione = 0.5;
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_EPOCHE; i++)
|
||||||
|
{
|
||||||
|
if (corrette == 4)
|
||||||
|
{
|
||||||
|
printf("\nEpoche necessarie: %d\n", i);
|
||||||
|
stampa_risultati_layer_multi(p_ext_1, p_ext_2, pout);
|
||||||
|
|
||||||
|
for (int z = 0; z < i; z++)
|
||||||
|
{
|
||||||
|
cls(tipo, 1);
|
||||||
|
traccia_retta(rette_p_ext_1[z].m, rette_p_ext_1[z].q, colore_rosso);
|
||||||
|
traccia_retta(rette_p_ext_2[z].m, rette_p_ext_2[z].q, colore_verde);
|
||||||
|
traccia_retta(rette_pout[z].m, rette_pout[z].q, colore_blu);
|
||||||
|
//printf("Sto tracciando la retta p1 con coefficiente: %f e intercetta: %f\n", rette_p_ext_1[z].m, rette_p_ext_1[z].q);
|
||||||
|
//printf("Sto tracciando la retta p2 con coefficiente: %f e intercetta: %f\n", rette_p_ext_2[z].m, rette_p_ext_2[z].q);
|
||||||
|
//printf("Sto tracciando la retta pout con coefficiente: %f e intercetta: %f\n", rette_pout[z].m, rette_pout[z].q);
|
||||||
|
stampa_epoca(z + 1);
|
||||||
|
sleep_ms(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
readkey();
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nEpoca %d\n", i);
|
||||||
|
corrette = 0;
|
||||||
|
|
||||||
|
for (int j = 0; j < 4; j++)
|
||||||
|
{
|
||||||
|
|
||||||
|
double y_ext_1 = funzione_sigmoide(p_ext_1, x[j][0], x[j][1]);
|
||||||
|
double y_ext_2 = funzione_sigmoide(p_ext_2, x[j][0], x[j][1]);
|
||||||
|
double yout = funzione_sigmoide(pout, y_ext_1, y_ext_2);
|
||||||
|
|
||||||
|
double errore = -(output[j] - yout);
|
||||||
|
int previsione = -1;
|
||||||
|
|
||||||
|
if (yout >= soglia_funzione_attivazione)
|
||||||
|
{
|
||||||
|
previsione = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
previsione = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
stampa_layer_uno(p_ext_1, y_ext_1, x[j][0], x[j][1], errore);
|
||||||
|
stampa_layer_out(pout, previsione, y_ext_1, y_ext_2, errore);
|
||||||
|
stampa_layer_uno(p_ext_2, y_ext_2, x[j][0], x[j][1], errore);
|
||||||
|
|
||||||
|
if (previsione == output[j])
|
||||||
|
{
|
||||||
|
corrette++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Gradienti percettrone 1
|
||||||
|
double gradiente_w1 = errore * yout * (1 - yout) * y_ext_1 * (1 - y_ext_1) * x[j][0];
|
||||||
|
double gradiente_w2 = errore * yout * (1 - yout) * y_ext_1 * (1 - y_ext_1) * x[j][1];
|
||||||
|
double gradiente_bias = errore * yout * (1 - yout) * y_ext_1 * (1 - y_ext_1);
|
||||||
|
correggi_pesi(&p_ext_1, gradiente_w1, gradiente_w2, gradiente_bias);
|
||||||
|
|
||||||
|
// Gradienti percettrone 2
|
||||||
|
gradiente_w1 = errore * yout * (1 - yout) * y_ext_2 * (1 - y_ext_2) * x[j][0];
|
||||||
|
gradiente_w2 = errore * yout * (1 - yout) * y_ext_2 * (1 - y_ext_2) * x[j][1];
|
||||||
|
gradiente_bias = errore * yout * (1 - yout) * y_ext_2 * (1 - y_ext_2);
|
||||||
|
correggi_pesi(&p_ext_2, gradiente_w1, gradiente_w2, gradiente_bias);
|
||||||
|
|
||||||
|
// Gradienti percettrone out
|
||||||
|
gradiente_w1 = errore * yout * (1 - yout) * y_ext_1;
|
||||||
|
gradiente_w2 = errore * yout * (1 - yout) * y_ext_2;
|
||||||
|
gradiente_bias = errore * yout * (1 - yout);
|
||||||
|
correggi_pesi(&pout, gradiente_w1, gradiente_w2, gradiente_bias);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevengo la divisione per zero
|
||||||
|
if(p_ext_1.w2 != 0 && p_ext_2.w2 != 0 && pout.w2 !=0)
|
||||||
|
{
|
||||||
|
rette_p_ext_1[i].m = -(p_ext_1.w1 * x[j][0]) / p_ext_1.w2;
|
||||||
|
rette_p_ext_1[i].q = -(p_ext_1.bias / p_ext_1.w2);
|
||||||
|
rette_p_ext_2[i].m = -(p_ext_2.w1 * x[j][0]) / p_ext_2.w2;
|
||||||
|
rette_p_ext_2[i].q = -(p_ext_2.bias / p_ext_2.w2);
|
||||||
|
rette_pout[i].m = -(pout.w1 * x[j][0]) / pout.w2;
|
||||||
|
rette_pout[i].q = -(pout.bias / pout.w2);
|
||||||
|
|
||||||
|
if (corrette != 4)
|
||||||
|
{
|
||||||
|
rette_p_ext_1 = (Retta *)realloc(rette_p_ext_1, sizeof(Retta) * (i + 2));
|
||||||
|
rette_p_ext_2 = (Retta *)realloc(rette_p_ext_2, sizeof(Retta) * (i + 2));
|
||||||
|
rette_pout = (Retta *)realloc(rette_pout, sizeof(Retta) * (i + 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
148
layer_singolo.c
148
layer_singolo.c
@@ -0,0 +1,148 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include "percettrone.h"
|
||||||
|
#include "grafico.h"
|
||||||
|
|
||||||
|
int MAX_EPOCHE = 10000;
|
||||||
|
/*
|
||||||
|
il tipo indica quali punti vogliamo disegnare nel grafico:
|
||||||
|
0: AND
|
||||||
|
1: OR
|
||||||
|
2: XOR
|
||||||
|
3: NAND
|
||||||
|
4: NOR
|
||||||
|
5: XNOR
|
||||||
|
*/
|
||||||
|
int tipo = 3;
|
||||||
|
|
||||||
|
void stampa_risultati(Percettrone);
|
||||||
|
void sleep_ms(int);
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
srand(time(NULL));
|
||||||
|
|
||||||
|
allegro_init();
|
||||||
|
install_keyboard();
|
||||||
|
set_gfx_mode(GFX_AUTODETECT_WINDOWED, 800, 600, 0, 0);
|
||||||
|
cls(tipo, 0);
|
||||||
|
|
||||||
|
int output[4];
|
||||||
|
switch (tipo)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
output[0] = 0;
|
||||||
|
output[1] = 0;
|
||||||
|
output[2] = 0;
|
||||||
|
output[3] = 1;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
output[0] = 0;
|
||||||
|
output[1] = 1;
|
||||||
|
output[2] = 1;
|
||||||
|
output[3] = 1;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
output[0] = 0;
|
||||||
|
output[1] = 1;
|
||||||
|
output[2] = 1;
|
||||||
|
output[3] = 0;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
output[0] = 1;
|
||||||
|
output[1] = 1;
|
||||||
|
output[2] = 1;
|
||||||
|
output[3] = 0;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
output[0] = 1;
|
||||||
|
output[1] = 0;
|
||||||
|
output[2] = 0;
|
||||||
|
output[3] = 0;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
output[0] = 1;
|
||||||
|
output[1] = 0;
|
||||||
|
output[2] = 0;
|
||||||
|
output[3] = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Percettrone p = crea_percettrone();
|
||||||
|
int colore_rosso = makecol(255, 0, 0);
|
||||||
|
|
||||||
|
// Contatore per fermare il percettrone, se vale 4 significa che ha indovinato tutte e 4 le combinazioni
|
||||||
|
int corrette = 0;
|
||||||
|
|
||||||
|
Retta *rette = (Retta *)malloc(sizeof(Retta));
|
||||||
|
|
||||||
|
// Soglia sigmoide
|
||||||
|
double soglia_funzione_attivazione = 0.5;
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_EPOCHE; i++)
|
||||||
|
{
|
||||||
|
if (corrette == 4)
|
||||||
|
{
|
||||||
|
printf("\nEpoche necessarie: %d\n", i);
|
||||||
|
stampa_risultati_layer_singolo(p);
|
||||||
|
|
||||||
|
for (int z = 0; z < i; z++)
|
||||||
|
{
|
||||||
|
cls(tipo, 0);
|
||||||
|
traccia_retta(rette[z].m, rette[z].q, colore_rosso);
|
||||||
|
//printf("Sto tracciando la retta con coefficiente: %f e intercetta: %f\n", rette[z].m, rette[z].q);
|
||||||
|
stampa_epoca(z + 1);
|
||||||
|
sleep_ms(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
readkey();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nEpoca %d\n", i);
|
||||||
|
corrette = 0;
|
||||||
|
|
||||||
|
for (int j = 0; j < 4; j++)
|
||||||
|
{
|
||||||
|
|
||||||
|
double y = funzione_sigmoide(p, x[j][0], x[j][1]);
|
||||||
|
|
||||||
|
double errore = -(output[j] - y);
|
||||||
|
int previsione = -1;
|
||||||
|
|
||||||
|
if (y >= soglia_funzione_attivazione)
|
||||||
|
{
|
||||||
|
previsione = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
previsione = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
stampa_layer_out(p, previsione, x[j][0], x[j][1], errore);
|
||||||
|
|
||||||
|
if (previsione == output[j])
|
||||||
|
{
|
||||||
|
corrette++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
double gradiente_w1 = errore * y * (1 - y) * x[j][0];
|
||||||
|
double gradiente_w2 = errore * y * (1 - y) * x[j][1];
|
||||||
|
double gradiente_bias = errore * y * (1 - y);
|
||||||
|
|
||||||
|
correggi_pesi(&p, gradiente_w1, gradiente_w2, gradiente_bias);
|
||||||
|
}
|
||||||
|
|
||||||
|
rette[i].m = -(p.w1 * x[j][0]) / p.w2;
|
||||||
|
rette[i].q = -(p.bias / p.w2);
|
||||||
|
|
||||||
|
if (corrette != 4)
|
||||||
|
{
|
||||||
|
rette = (Retta *)realloc(rette, sizeof(Retta) * (i + 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
percettrone
BIN
percettrone
Binary file not shown.
@@ -1,48 +0,0 @@
|
|||||||
#include <stdlib.h>;
|
|
||||||
#include <stdio.h>;
|
|
||||||
#include <time.h>;
|
|
||||||
|
|
||||||
Percettrone p1 = creaPercettrone();
|
|
||||||
Percettrone p2 = creaPercettrone();
|
|
||||||
Percettrone p3 = creaPercettrone();
|
|
||||||
|
|
||||||
struct struttura_percettrone {
|
|
||||||
double w1;
|
|
||||||
double w2;
|
|
||||||
double bias;
|
|
||||||
double lre;
|
|
||||||
};
|
|
||||||
typedef struct struttura_percettrone Percettrone;
|
|
||||||
|
|
||||||
Percettrone creaPercettrone() {
|
|
||||||
srand(time(NULL));
|
|
||||||
|
|
||||||
Percettrone percettrone;
|
|
||||||
|
|
||||||
percettrone.w1 = random();
|
|
||||||
percettrone.w2 = random();
|
|
||||||
percettrone.bias = random();
|
|
||||||
percettrone.lre = 0.2;
|
|
||||||
|
|
||||||
return percettrone;
|
|
||||||
}
|
|
||||||
|
|
||||||
double random() {
|
|
||||||
// Genero numeri nell'intervallo [-1,1]
|
|
||||||
return ((double)(rand() % 101 * 0.01 * 2 ) -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
creaPercettrone();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* # il return verrà confrontato col valore di soglia di attivazione
|
|
||||||
def funzione_sigmoide(self, x1, x2):
|
|
||||||
return (1 / (1 + math.exp(-((x1 * self.w1) + (x2 * self.w2) + self.bias))))
|
|
||||||
|
|
||||||
def correggi_pesi(self, gradiente_w1, gradiente_w2, gradiente_bias):
|
|
||||||
self.bias = self.bias - (gradiente_bias * self.lre)
|
|
||||||
self.w1 = self.w1 - (gradiente_w1 * self.lre)
|
|
||||||
self.w2 = self.w2 - (gradiente_w2 * self.lre) */
|
|
||||||
94
percettrone.h
Normal file
94
percettrone.h
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
double LRE = 0.2;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
double w1;
|
||||||
|
double w2;
|
||||||
|
double bias;
|
||||||
|
double lre;
|
||||||
|
} Percettrone;
|
||||||
|
|
||||||
|
// Inputs
|
||||||
|
int x[4][2] = {
|
||||||
|
{0, 0},
|
||||||
|
{0, 1},
|
||||||
|
{1, 0},
|
||||||
|
{1, 1},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Dichiarazione dei metodi
|
||||||
|
Percettrone crea_percettrone();
|
||||||
|
double randomico();
|
||||||
|
double funzione_sigmoide(Percettrone, double, double);
|
||||||
|
void correggi_pesi(Percettrone*, double, double, double);
|
||||||
|
|
||||||
|
void stampa_layer_uno(Percettrone, double, int, int, double);
|
||||||
|
void stampa_layer_out(Percettrone, int, double, double, double);
|
||||||
|
void stampa_risultati_layer_singolo(Percettrone);
|
||||||
|
void stampa_risultati_layer_multi(Percettrone, Percettrone, Percettrone);
|
||||||
|
|
||||||
|
Percettrone crea_percettrone() {
|
||||||
|
|
||||||
|
Percettrone percettrone;
|
||||||
|
|
||||||
|
percettrone.w1 = randomico();
|
||||||
|
percettrone.w2 = randomico();
|
||||||
|
percettrone.bias = randomico();
|
||||||
|
percettrone.lre = LRE;
|
||||||
|
|
||||||
|
return percettrone;
|
||||||
|
}
|
||||||
|
|
||||||
|
double randomico() {
|
||||||
|
// Genero numeri nell'intervallo [-1,1]
|
||||||
|
return ((double)(rand() % 101 * 0.01 * 2 ) -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
double funzione_sigmoide(Percettrone p, double x1, double x2) {
|
||||||
|
double funzione = (x1 * p.w1) + (x2 * p.w2) + p.bias;
|
||||||
|
double potenza_e = exp(-funzione);
|
||||||
|
double risultato = 1 / ( 1 + potenza_e);
|
||||||
|
|
||||||
|
return risultato;
|
||||||
|
}
|
||||||
|
|
||||||
|
void correggi_pesi(Percettrone *p, double grad_w1, double grad_w2, double grad_bias) {
|
||||||
|
(*p).bias = (*p).bias - (grad_bias * (*p).lre);
|
||||||
|
(*p).w1 = (*p).w1 - (grad_w1 * (*p).lre);
|
||||||
|
(*p).w2 = (*p).w2 - (grad_w2 * (*p).lre);
|
||||||
|
}
|
||||||
|
|
||||||
|
void stampa_layer_uno(Percettrone p, double y, int x1, int x2, double errore)
|
||||||
|
{
|
||||||
|
printf("\n");
|
||||||
|
printf("\tW1: %f\n", p.w1);
|
||||||
|
printf("X1: %d --------> \n", x1);
|
||||||
|
printf("\t\t( bias: %f ) -------> Y: %f, errore: %f\n", p.bias, y, errore);
|
||||||
|
printf("X2: %d --------> \n", x2);
|
||||||
|
printf("\tW2: %f\n", p.w2);
|
||||||
|
printf("\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void stampa_layer_out(Percettrone p, int y, double x1, double x2, double errore) {
|
||||||
|
printf("\t\t\t\t\t\tW1: %f\n", p.w1);
|
||||||
|
printf("\t\t\t\t\tX1: %f --------> \n", x1);
|
||||||
|
printf("\t\t\t\t\t\t\t( bias: %f ) -------> Y: %d, errore: %f\n", p.bias, y, errore);
|
||||||
|
printf("\t\t\t\t\tX2: %f --------> \n", x2);
|
||||||
|
printf("\t\t\t\t\t\tW2: %f\n", p.w2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void stampa_risultati_layer_singolo(Percettrone p) {
|
||||||
|
printf("\nPercettrone:\n");
|
||||||
|
printf("\t W1: %f, W2: %f, bias: %f\n", p.w1, p.w2, p.bias);
|
||||||
|
}
|
||||||
|
|
||||||
|
void stampa_risultati_layer_multi(Percettrone p1, Percettrone p2, Percettrone pout) {
|
||||||
|
printf("\nPercettrone 1:\n");
|
||||||
|
printf("\t W1: %f, W2: %f, bias: %f\n", p1.w1, p1.w2, p1.bias);
|
||||||
|
printf("Percettrone 2:\n");
|
||||||
|
printf("\t W1: %f, W2: %f, bias: %f\n", p2.w1, p2.w2, p2.bias);
|
||||||
|
printf("Percettrone OUT:\n");
|
||||||
|
printf("\t W1: %f, W2: %f, bias: %f\n", pout.w1, pout.w2, pout.bias);
|
||||||
|
}
|
||||||
0
stampe_video.h
Normal file
0
stampe_video.h
Normal file
1
tempCodeRunnerFile.c
Normal file
1
tempCodeRunnerFile.c
Normal file
@@ -0,0 +1 @@
|
|||||||
|
-3
|
||||||
Reference in New Issue
Block a user