Pages: 1 ... 4 5 [6] 7 8 ... 10   Go Down
Author Topic: Semplice rete neurale per Arduino 2  (Read 14177 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Shannon Member
****
Karma: 132
Posts: 10498
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
l tuo sketch poi è sbagliato visto che usi sin(x) che è proprio la funzione che sto tentando di approsimare partendo dai set in ingresso
lo faccio solo per avere lo stesso identico set per fare l'addestrameto e poi il check. Se non funziona c'è qualche bug nella libreria. Se funziona il bug è nella funzione di input.
Tu stai pensando all'utilizzo, io al debug, e procedo per gradi.

Quote
Quando faccio Serial.parseFloat()/360 è proprio perchè voglio dividerlo per 360 cioè far rientrare l'angolo tra 0 ed 1. Il % cioè il resto non c'entra niente.
mi sono perso questa normalizzazione dell'uso dei gradi. Sapevo che l'output deve essere un valore tra -1 e 1 però, cosa che /360 fà se metti angoli negativi.

Quote
rete ha solo un ingresso ed una uscita allora passo l'indirizzo della variabile (o della cella dell'array). È la rete che poi gestisce in automatico il numero di ingressi (uso la magia dei puntatori in poche parole  smiley-mr-green).

ora mi è chiaro, quindi nel mio codice c'è da cambiare

Code:
net.backPropagation(i, sin(i),LR);
in
Code:
net.backPropagation(&i, &(sin(i)),LR);

e

Code:
Serial.println( sin(i)-net.thinkNet(i) );
in
Code:
Serial.println( sin(i)-(*net.thinkNet(&i)) );

Quote
Il tuo post è completamente sbagliato o quasi.
dai non era così pessimo smiley
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 333
Posts: 22966
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ma sin() già non restituisce un valore compreso tra 1 e -1?
Sin 0 = 0
Sin 90 = 1
Sin 180 = 0
Sin 270 = -1
Sin 360 = 0
Logged


Offline Offline
Sr. Member
****
Karma: 4
Posts: 363
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@lesto:
Ok, se lo si guarda da un punto di vista del debug ci può stare sin(x)  smiley. Completamente sbagliato no, l'ho detto per evitare che fosse troppo fuorviante per chi sta leggendo la discussione e non sa nulla sulle reti neurali.
Per quanto riguarda il debug sono sicuro che la libreria funzioni perchè l'ho passata su code::blocks e funziona senza quasi modifiche (che ricordo coinvolgono l'importazione di cmath.h per usare exp() e la modifica di random() in rand()). I training sets non sono neppure quelli perchè li uso senza problemi e nemmeno la firma di thinkNet(). L'unica cosa che posso pensare appunto è lo sketch di prova che verificava continuamente il pin4 per l'addestramento e aveva qualcosa che non andava(non so cosa) oppure i settaggi iniziali della rete.

@leo72
Non ho capito cosa intendi.
« Last Edit: May 09, 2013, 04:30:28 pm by yoshi93 » Logged

0
Offline Offline
Shannon Member
****
Karma: 132
Posts: 10498
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ma sin() già non restituisce un valore compreso tra 1 e -1?
Sin 0 = 0
Sin 90 = 1
Sin 180 = 0
Sin 270 = -1
Sin 360 = 0


attento che lavora in radianti. quindi 180° sono PI (~3.14), 360° sono 2PI (~6.28) etc..

Quote
Scrivere:
Code:

(rand()%100)/1000.0

è uguale a:
Code:

random(100)/1000.0

vero?

sì, se può essere utile: http://arduino.cc/en/Reference/HomePage

attento che rand()%100 è "sbagliato", rovini la distribuzione dei numeri casuali, di solito nulla di che, ma se usi la rand() spesso può dare problemi http://www.azillionmonkeys.com/qed/random.html
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Offline Offline
Sr. Member
****
Karma: 4
Posts: 363
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@lesto:
Non ho capito a chi ti riferisci quando dici
Quote
attento che lavora in radianti
.
Per la rand() invece il problema è che lei funziona perfettamente su pc e il mio dubbio era la random() di arduino.
Ci vorrebbero altre prove con i valori dello sketch modificati per vedere come va.
Logged

0
Offline Offline
Shannon Member
****
Karma: 132
Posts: 10498
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

per la storia dei radianti parlavo con leo, che ha fatto un esempio della sin() usando i gradi.  smiley-mr-green
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

0
Offline Offline
Sr. Member
****
Karma: 4
Posts: 477
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ma sin() già non restituisce un valore compreso tra 1 e -1?

Se non ricordo male vanno normalizzati sia gli ingressi che le uscite sia nell'addestramento che poi nell'uso.


Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 333
Posts: 22966
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

@yoshi e lesto
mi riferivo a questo pezzo di yoshi:
Gli angoli non sono in radianti ma bensì in gradi normalizzati tra 0 ed 1 come già detto e il seno è trasformato secondo quella formula per far coincidere lo della funzione con il valore 0.5 della funzione sigmoide usata dai neuroni.
In pratica, il neurone di uscita ha una funzione sigmoide(come tutti gli altri) e il sin(0)=sin(360)=0. 0 e 360 sono presenti nei set di addestramento due volte percui la rete tenderà a convergere con maggiore precisione sullo 0 ma poichè ha funzione sigmoide sullo 0 non ci potrà mai andare visto che ha un andamento asintotico per -infinito percui lo 0 (normalizzato a 0) e 360(normalizzato a 1) hanno valori di uscita dalla rete di 0.5 che equivale a sigmoid(0) per avere la massima precisione possibile proprio intorno a quel punto.

Estratto dal Reference:
Quote
Description
Calculates the sine of an angle (in radians). The result will be between -1 and 1.
sin lavora in radianti ma il suo risultato è sempre compreso fra -1 e 1.
Logged


Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 333
Posts: 22966
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Nuove prove con l'ultima versione della lib e l'ultima versione dello sketch:

sin 0 = 1.30
sin 45 = 1.08
sin 90 = 0.88
sin 135 = 0.69
sin 180 = -0.01
sin 225 = -0.62
sin 270 = -0.65
sin 315 = -0.65
sin 360 = -0.65
Logged


0
Offline Offline
Shannon Member
****
Karma: 132
Posts: 10498
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ok, verifichiamo che ogni tot di fase di addestramento l'errore diminuisca: (ripropongo il mio codice rivisto e corretto, spero)

Code:
#include <StaticNeuron.h>
#include <ArdFeedForward.h>

const float LR=0.2;
const unsigned int TRAINING_CYCLES=1000;
unsigned int ciclo=0;

ArdFeedForward net(1,1,2,2);

void setup()
{
Serial.begin(9600);
delay(1000);
}

void loop(){
ciclo++;
Serial.print("Inizio addestramento ");
Serial.print(ciclo);
Serial.print(" di ");
Serial.print( TRAINING_CYCLES );
Serial.print(" cicli ");
Serial.println(); //a capo

//fase di training
for(int j=0;j<TRAINING_CYCLES;j++){
for(int i=0;i<17;i++){
net.backPropagation(&i, &(sin(i)),LR);
}
}

float sumErrore =0; //ci aspettiamo che ogni ciclo questo valore diminuisca
for(int i=0;i<30;i++){
sumErrore += abs( sin(i)-(*net.thinkNet(&i)) ); //somma il modulo dell'errore, per evitare che errori negativi apiattiscano erroneamente la soimma dell'errore
if (ciclo%40==0){
Serial.print("Per il seno di ");
Serial.print(i);
Serial.print(" l'errore è ");
Serial.print( sin(i)-(*net.thinkNet(&i)) );
Serial.println(); //a capo
}
}
Serial.print("La somma del modulo dell'errore è ");
Serial.print(sumErrore);
Serial.println(); //a capo
}
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Offline Offline
Sr. Member
****
Karma: 4
Posts: 363
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Mi stavo chiedendo, potrebbe essere un problema del compilatore? Il mio progetto fa un uso smodato di puntatori quindi non è che magari l'arduino va in errore per qualche errore interno?
Logged

0
Offline Offline
Shannon Member
****
Karma: 132
Posts: 10498
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

no, la due è un ARM, architettura molto più diffusadegli AVR. Sarebbe un signor bug  smiley-mr-green
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Offline Offline
Sr. Member
****
Karma: 4
Posts: 363
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Oppure più semplicemente sforo con la ram smiley-roll-sweat. Comunque devo ammettere che il porting da pc non è stata una buona idea, la rete così strutturata è troppo pesante e capire dove siano i problemi è piuttosto difficoltoso. Questo post mi ha fornito molte informazioni riguardo l'ottimizzazione che potrei fare. Credo che nella prossima versione non userò più la StaticNeuron per risparmiare spazio (rimane comunque a disposizione per eventuali prove).
Se leo è d'accordo dovrei avere anche un nuovo post pulito per lavorare anche sull'ordine della discussione.
Logged

Rome/Italy
Offline Offline
Newbie
*
Karma: 1
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Buonasera a tutti i partecipanti alla discussione.

@Yoshi93, innanzi tutto grazie per aver aperto la discussione, sebbene è un argomento un po' ostico, credo che potrebbe consentirci interessanti applicazioni sulla piattaforma Arduino.
Mi viene in mente per esempio la possibilità di prendere una decisione sul valore di più sensori, come farebbe un esperto.
Sono riuscito a far funzionare il codice, senza modificare la tua libreria ma solo modificando il tuo sketch.

Ho caricato sul mio Arduino Due la tua libreria e lo sketch che avevi postato qualche giorno fa e ho utilizzato LR = 0.5 come suggerito sul sito http://stor.altervista.org/informatica/nn/nn.htm

Dopo aver eseguito molti test, inserendo qualche traccia su input ed output mi sono reso conto che la comunicazione seriale non lavorava correttamente. La Serial.ParseFloat() alla prima lettura leggeva l'angolo correttamente e infatti il primo risultato era corretto, alle letture successive invece non leggeva il primo carattere, quindi se immettevi 30, 60, 70 ecc, restituiva sempre 0.1 perchè leggeva zero e comunque valori molto bassi se si provavano .
Il valore del seno dell'angolo è calcolato con l'approssimazione di 0.01, ma l'esempio ci assicura che il tuo codice è affidabile, dato che non è la precisione matematica lo scopo della cosa.

Ho pensato quindi di costruirmi una funzione per fare il parsing dell'input dell'angolo, in modo da leggere valori positivi e negativi e ho inserito come delimitatore il carattere ";".

Ho anche semplificato il tuo sketch mettendo la fase di Addestramento nella sezione setup. L'addestramento dura circa 6 minuti, ho inserito due chiamate, sebbene dopo la prima mi pare che i risultati sono già buoni.
Inserisco il codice così se quancuno se vuole può provare a ripetere la verifica.
Spero si possa proseguire nel migliorare  per arrivare ad addestrare la rete con input provenienti da sensori.
Non so se in questo Yoshi93 può darci qualche idea riguardo la definizione dei dati di addestramento.
ciao a tutti

* sketch rete neurale.txt (2.31 KB - downloaded 18 times.)
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 333
Posts: 22966
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Se leo è d'accordo dovrei avere anche un nuovo post pulito per lavorare anche sull'ordine della discussione.
Risposto in PM.
Logged


Pages: 1 ... 4 5 [6] 7 8 ... 10   Go Up
Jump to: