Go Down

Topic: Semplice rete neurale per Arduino 2 (Read 15406 times) previous topic - next topic

yoshi93

#15
Apr 07, 2013, 08:36 pm Last Edit: Apr 08, 2013, 11:32 am by yoshi93 Reason: 1
Prova con questo quando hai un po' di tempo:
Code: [Select]

#include <StaticNeuron.h>
#include <ArdFeedForward.h>
#define LearnPin 4

float LR=0.2;
int TRAINING_CYCLES=100000;
float desiredOut[]={0.5000,0.6531,0.7828,0.8696,0.9000,0.8696,0.7828,0.6531,0.5000,0.3469,0.2172,0.1304,0.1000,0.1304,0.2172,0.3469,0.5000};
float inputs[]={0.0000,0.0625,0.1250,0.1875,0.2500,0.3125,0.3750,0.4375,0.5000,0.5625,0.6250,0.6875,0.7500,0.8125,0.8750,0.9375,1.0000};

ArdFeedForward net(1,1,5,5);

void nop() {}
void setup()
{
 Serial.begin(9600);
 pinMode(LearnPin,INPUT);
}
void loop()
{
 if(digitalRead(LearnPin)==1) //addestra la rete neurale per TRAINING_CYCLES cicli
 {
   for(int j=0;j<TRAINING_CYCLES;j++)
     for(int i=0;i<17;i++)
       net.backPropagation(&inputs[i],&desiredOut[i],LR);
 }
 else //usa la rete neurale
 {
   Serial.println("Inserisci l'angolo di cui vuoi sapere il seno");
   while(!Serial.available()) nop();
   float x=Serial.parseFloat()/360;
   Serial.println((*net.thinkNet(&x)-0.1)*2/0.8-1);
 }
}


P.S. I set di addestramento li ho presi da http://stor.altervista.org/informatica/nn/nn.htm dove c'è anche una infarinatura generale sulle reti neurali.

leo72

Compila, carica e funziona... o per lo meno immagino che funzioni  ;)
Non so esattamente che fa.
Mi chiede un angolo, glielo inserisco e lui mi restituisce un valore decimale. Ho provato una decina di valori...
Code: [Select]

Inserisci l'angolo di cui vuoi sapere il seno
0.08
Inserisci l'angolo di cui vuoi sapere il seno
0.08
Inserisci l'angolo di cui vuoi sapere il seno
0.06
Inserisci l'angolo di cui vuoi sapere il seno
0.06
Inserisci l'angolo di cui vuoi sapere il seno
0.05
Inserisci l'angolo di cui vuoi sapere il seno
0.08
Inserisci l'angolo di cui vuoi sapere il seno
0.08
Inserisci l'angolo di cui vuoi sapere il seno
0.08
Inserisci l'angolo di cui vuoi sapere il seno


PS:
con calma mi leggerò la pagina che mi hai linkato.

yoshi93

Dovrebbe restituire il seno dell'angolo che hai inserito come input dopo aver addestrato la rete mettendo a 3.3V il pin 4.(Teoricamente)

leo72

Non capisco questo:
Code: [Select]
if(digitalRead(LearnPin==1))

Siccome definisci LearnPin come 4,
il codice sarebbe:
Code: [Select]
if(digitalRead(4==1))
Ma 4 è diverso da 1, quindi dovrebbe leggere il pin 0 (0 è false).
O mi sfugge qualcosa?

yoshi93

No, non ti sfugge niente, è stato un mio errore, dovrebbe essere if(digitalRead(LearnPin)==1). Che errore stupido.

leo72

Sì, funziona. Ma non so che faccia né se lo fa correttamente :smiley-yell:
'ste reti neurali sono una cosa astrusa per me  :smiley-sweat: :smiley-sweat:

Cmq hai fatto un be lavoro, il tuo codice funziona. Compila e lavora senza problemi sulla DUE, anche se ciuccia più di 75.000 byte di flash  :smiley-eek:

yoshi93

#21
Apr 07, 2013, 11:25 pm Last Edit: Apr 07, 2013, 11:27 pm by yoshi93 Reason: 1
Purtroppo le reti neurali sono pesantucce. Cmq se mi posti gli input che metti e i relativi output posso dirti se sta facendo il suo sporco lavoro. Oppure se hai una calcolatrice scientifica puoi farlo tu. Ovviamente ricordo sempre di addestrarla prima.

P.S. Grazie a te e alla tua disponibilità.

leo72

Beh, io ho dato i 3V3 al pin per un pò di secondi, poiho iniziato a passare dei valori a caso compresi fra 1 e 90.
Ad esempio 12, 56, 90.
Però ricevo sempre 0.02.

yoshi93

#23
Apr 07, 2013, 11:59 pm Last Edit: Apr 08, 2013, 12:06 am by yoshi93 Reason: 1
Non ci siamo quindi, vabbè proverò a rifare il porting arduino->pc e vedere se ho fatto qualche semplificazione di troppo. Purtroppo questa settimana sono bloccato quindi ci metterò un po'.

P.S. Guardando il codice ho notato un'altro bug nella trasformazione dell'angolo di ingresso. leo72 hai un'anima così pia da riprovare e dirmi come va te ne sarei grato.(Ho modificato lo sketch)

leo72

Questo è l'output. I primi valori sono prima dell'addestramento, quelli negativi dopo (ovviamente numeri sempre diversi):
Code: [Select]
Inserisci l'angolo di cui vuoi sapere il seno
0.08
Inserisci l'angolo di cui vuoi sapere il seno
0.08
Inserisci l'angolo di cui vuoi sapere il seno
-1.25
Inserisci l'angolo di cui vuoi sapere il seno
-1.25
Inserisci l'angolo di cui vuoi sapere il seno
-1.25
Inserisci l'angolo di cui vuoi sapere il seno
-1.25
Inserisci l'angolo di cui vuoi sapere il seno

lesto

leo una rete neurale è in pratica un programma in grado di apprendere.

Però prima va "addestrata": ovvero devi dargli degli input e l'output aspettato. In questo modo, la rete autoricalcola dei valori all'interno dei suoi neuroni in modo che all'input corrisponda un output.

Quindi metti il pin a 3,3v e metti il valore dell'angolo e il suo seno calcolato con la calcolatrice, dopo quanche migliaio (bhe dipende dalla rete) di inserimenti vedrai che togliendo il pin a 3,3 i valori della rete saranno corretti; la rete neurale ha funzionato!

ma non è così facile come sembra. A seconda dei tipi di neuroni che usi (che sono COPIE del funzionamento dei neuroni animali, per esempio i lineari sono copie dei neuroni della corteccia celebrale) e dei tipo di collegamento tra i neuroni potresti avere risultati differenti, instabili e persino (anzi spesso) non in grado di  imparare il tuo specifico problema.

Poi di solito non si usa una rete, ma un array di reti detta generazione: ogni tot dalla generazione vengono scelti gli esemplari "migliori" e rigenerato l'array a partire da questi inserendo delle copie esatte e delle copie con errori random (mutazioni); questo procedimento è detto "algoritmo genetico" perchè come noti imita l'evoluzione e la selezioni naturale!
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

leo72

Ma lo sketch che mi ha passato yoshi93 non mi pare che chieda i 2 valori, cioè l'angolo di cui calcolare il seno ed il seno stesso.
O non ho capito io come funziona? Se io dò i 3V3 al pin 4, semplicemente la scheda non mi chiede nulla.

Altra cosa, cercando in rete si trovano anche delle implementazioni (limitate a pochi neuroni) di reti neurali anche per Arduino UNO. Considerando che questa consuma 75 kB, immagino che sia una rete neurale power;)
Mi fai un altro esempio di rete neurale? Cioè, che ci potrei fare? Potrebbe essermi utile in qualcosa?

Per ora ci ho capito poco però quel poco è affascinante  :smiley-sweat:

yoshi93

@lesto:
ottima spiegazione.
Riguardo gli algoritmi genetici hai qualcosa da consigliarmi? Io ho letto e studiato per ora Evolutionary Robotics però ora vorrei qualche esempio in più per farmi una idea sulle codifiche delle stringhe genetiche per scriverne una mia che ho in mente.

@leo72:
1)i valori ci sono di addestramento ci sono, sono salvati nei due array ad inizio sketch. Sempilicemente mettendo il pin 4 a a 3.3 il programma preleva i valori di addestramento dai due array. Quello che ti ho passato è solo un programma di test.

2)Compilata occupa tanto perchè è la libreria che è power (ma neanche tanto) poichè è fatta con le classi invece di struct per motivi di semplicità e usabilità (sacrificando però un po' di ottimizzazione). La rete presente nello sketch è composta da 5 neuroni quindi in effetti non è poi una cosa così mostruosa.

3)Mi potresti linkare le pagine dove ci sono le reti neurali per Arduino UNO?

lesto

io ci ho lavorato poco, giusto per far capire anche a leo, ne ho creata una per robocode, un gioco dove devi scrivere in java la AI di un carro armato.
ho provato la NN come uno dei possibili algoritmi per mirare l'avversario... quì trovate un mondo di info, anche se alla fine sono state abbandonate http://old.robowiki.net/robowiki?NeuralTargeting

In pratica io codicficavo il movimento dell'aversario in 9 caselle, ogni turno era una casella, insegnavo il movimento alla NN, e poi mi facevo predire il prossimo turno, lo aggiungevo all'input (senza learning) e via di predizioni finché non avevo il numero di turni impiegati al proiettile per arrivare alla posizione stimata del nemico. poi sparavo in quella direzione (nel gioco NON si vedono i proiettili in gioco, rendendola sfida assai interessante)

1. potresti usare la sin() e usare i valori da -1 a 1 in un for. e dopo il learning fare sempre un for che chiama sia la sin() che la NN, e calcolare lo sfaso.

2. il vantaggio di una NN è che occupa un tot di ram fisso, quindi puoi riempire quasi tutta la ram lasciando solo 100/200 byte liberi per lo stack e le variabili temporanee
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

leo72

@yoshi:
io ho semplicemente cercato "neural network arduino" su Google. Già aprendo i primi 3/4 risultati si giunge a degli esempi di reti neurali.
Però non ho la conoscenza per dirti se sono finte reti oppure se è qualcosa di valido.

Go Up