Semplice rete neurale per Arduino 2

Salve a tutti,
ho realizzato questi semplici moduli in C++ per gestire reti neurali feedforward da 3 strati con backpropagation come algoritmo di apprendimento. Visto che per arduino non ho visto niente di concreto su questo argomento ho deciso di mettere a disposizione il mio codice come possibile base per altri progetti.
Probabilmente le classi e alcune cose dovranno essere modificate un po' poichè sono state progettate per computer normali.

EDIT 11/7/2013:

-Il primo file nell'area dei download è la libreria per l'invio/ricezione di float/long come bytes. La durata della trasmissione non dipende più quindi da quante cifre è composto il numero. È anche compatibile con Arduino UNO.

-Il secondo file è la libreria per le reti neurali (solo arduino DUE) e contiene al suo interno una copia della prima. Nell'archivio c'è anche uno sketch di prova.

ByteSerial.zip (2.27 KB)

ArdFeedForward.zip (5.79 KB)

Cosa significa questo?
Metti un programma che non é per Arduino? Poi con una compressione poco diffusa che si apre neanche.
Cosa speri di ottenere?

Uwe Federer
Moderatore

Non è che se non è per arduino non serva a niente, dopotutto siamo su un forum di un progetto open source. Io non ho mai usato arduino molto spesso però credo che quello che ho fatto possa servire come base per qualcuno.
P.S. Il formato 7z è molto usato, è molto meglio del rar e del zip e poi tutti i programmi che lo gestiscono sono gratis percui mi sembrava perfetto da usare su questo forum.

yoshi93:
Non è che se non è per arduino non serva a niente, dopotutto siamo su un forum di un progetto open source. Io non ho mai usato arduino molto spesso però credo che quello che ho fatto possa servire come base per qualcuno.
P.S. Il formato 7z è molto usato, è molto meglio del rar e del zip e poi tutti i programmi che lo gestiscono sono gratis percui mi sembrava perfetto da usare su questo forum.

A me dice che l'archivio è danneggiato...

quoto cece99

yoshi93:
dopotutto siamo su un forum di un progetto open source.

Siamo su un forum dove si parla di Arduino, non siamo un servizio di conversione programmi scritti per PC su Arduino.
Il file che hai allegato è corrotto.

Sì, è vero, il file è corrotto. Probabilmente c'è stato un errore quando l'ho caricato. Ascanso di equivoci posto direttamente tutto il codice:

update: Il codice è presente come allegato in uno dei post successivi.

Per quanto riguarda il servizio di conversione lo so, non è simpatico ritrovarsi codice che bisogna modificare ma dopotutto è sempre meglio che non avere nulla su cui lavorare se si è alle prime armi con questo argomento. Comunque le modifiche per fare una libreria non dovrebbero essere così sostanziali, da quello che ho visto sulle guide si tratta di importare il file "Arduino.h" e altre piccolezze. Non l'ho fatto io perchè credo che qualcuno che lavora su arduino in maniera costante sia più qualificato di me per questi lavori.

Guardando brevemente il codice e notate le notevoli volte che vengono create variabili e poi disallocate, dubito che possa girare su un Arduino. La conversione magari si può anche fare, ma Arduino non è un PC con grande memoria e su cui viene fatta la garbage collection, ovvero la pulizia della memoria.
Facile su Arduino occupare in breve tutta la RAM. Già da qualche problema la classe String se non usata bene.

Bisognerebbe provare solo che io non ho arduino 2.

@yoshi93:
scusami, non ho capito bene.
Questo programma che hai scritto e che hai allegato al momento non è per Arduino ma per un normale computer, giusto?
Tu non hai però una scheda Arduino per poter provare se la conversione è possibile, è così?
Quindi offri il codice per la gestione delle reti neurali a chi ha voglia di trasformarlo in uno sketch Arduinico, giusto?

La cosa potrebbe essere interessante e fattibile.
Forse da rivedere un po' perché le risorse di un Arduino UNO sono limitate. Magari un Arduino DUE lo può gestire senza problemi, viste le caratteristiche superiori.

Ti posso fare una domanda? Non sono un esperto, per cui ti chiedo anche a nome degli altri: a che serve una rete neurale?
Che ci si può fare? Sono curioso. :wink:

PS:
tralasciamo gli screzi sul formato 7z. Io lo conosco e lo uso da molto tempo, ci sono disponibili diversi programmi sia per Linux che per Windows che possono aprire archivi 7z. Visto però che non è lo standard, è sempre consigliabile utilizzare formati largamente diffusi (ecco perché anch'io che ho Linux distribuisco il mio software in formato zip e non per esempio 7z o tar.bz2) o, al massimo, offrire 2 alternative (zip e 7z) così uno si scarica quello che reputa migliore.

yoshi93:
Bisognerebbe provare solo che io non ho arduino 2.

Se presenti, aiuti o chiedi aiuto su problematiche, progetti o applicazioni su Arduino sei benvenuto in questo Forum.

Se metti qualcosa che non ha niente a che fare con Arduino per sentirti "grande" é meglio che lo lasci stare e ti tieni lontano perché dai solo fastidio.

No ha senso che presenti del codice che non ha niente a che fare con Arduino e che non sei neanche intenzionato a provare su Arduino.
Un Arduino DUE costa meno di 50 € spedizione compresa.

Ciao Uwe Federer
Moderatore

Una rete neurale serve essenzialmente per far apprendere una funzione ad una macchina partendo da un set di input con relativi output. La rete neurale approsimerà la funzione anche per valori di input non presenti nel set. Ovviamente più campioni fornisci più l'approsimazione sarà fine. Il coefficiente di apprendimento serve per determinare la velocità di apprendimento. Valori bassi genereranno un apprendimento fine ma che potrebbe incappare in soluzioni sub-ottime mentre un coefficiente elevato produrrà più oscillazioni nella fase di back-propagation risultando in funzioni più grossolane ma che probabilmente tenderanno a convergere verso la soluzione ottima.

@UweFederer
La tua logica secondo me uccide quello che sta alla base del progetto arduino cioè la condivisione di sapere. Come ho già detto ho postato il codice perchè ho visto che su questo argomento in questo forum c'era ben poco. Se poi per far parte del club bisogna per forza postare solo codice per arduino allora mi tolgo di mezzo. Faccio notare comunque che il mio programma funziona mentre molti altri che magari riguardano arduino richiedono molti post per essere corretti.
P.S. Io ho arduino UNO su cui sto progettando una libreria apposta per le reti neurali, per adesso della due non mi importa molto visto che non la userei per niente. Ho postato il codice per dare una base a qualcuno che ne possiede una.
P.P.S. Ti riformulo il post così si adatta di più alla tua visione :"Ho bisogno di una mano per modificare un programma sulle reti neurali. Come si fa una libreria per Arduino?"

yoshi93:
Una rete neurale serve essenzialmente per far apprendere una funzione ad una macchina partendo da un set di input con relativi output. La rete neurale approsimerà la funzione anche per valori di input non presenti nel set. Ovviamente più campioni fornisci più l'approsimazione sarà fine. Il coefficiente di apprendimento serve per determinare la velocità di apprendimento. Valori bassi genereranno un apprendimento fine ma che potrebbe incappare in soluzioni sub-ottime mentre un coefficiente elevato produrrà più oscillazioni nella fase di back-propagation risultando in funzioni più grossolane ma che probabilmente tenderanno a convergere verso la soluzione ottima.

Non ci ho capito molto... :sweat_smile:
Ma un esempio pratico? Cioè, "con una rete neurale io posso.... completare la frase "

@UweFederer
La tua logica secondo me uccide quello che sta alla base del progetto arduino cioè la condivisione di sapere. Come ho già detto ho postato il codice perchè ho visto che su questo argomento in questo forum c'era ben poco. Se poi per far parte del club bisogna per forza postare solo codice per arduino allora mi tolgo di mezzo. Faccio notare comunque che il mio programma funziona mentre molti altri che magari riguardano arduino richiedono molti post per essere corretti.
P.S. Io ho arduino UNO su cui sto progettando una libreria apposta per le reti neurali, per adesso della due non mi importa molto visto che non la userei per niente. Ho postato il codice per dare una base a qualcuno che ne possiede una.
P.P.S. Ti riformulo il post così si adatta di più alla tua visione :"Ho bisogno di una mano per modificare un programma sulle reti neurali.

Mi sembra che alla base di tutto ci sia del fraintendimento.
Tu hai un codice per PC funzionante ed una scheda Arduino.
Vorresti provare a fare una libreria per Arduino ma non sai da che parte rifarti.
Non hai pubblicato tutto perché qualcuno lo faccia al posto tuo.
Ho capito bene?

Come si fa una libreria per Arduino?"

Con una rete neurale puoi ottenere la funzione sin(x) partendo dai valori che conosci ovviamente approsimata di molto per gli input non presenti nel set di addestramento. Oppure usando il convertitore analogico puoi campionare un segnale e addestrare una rete per riprodurlo o per usarlo come funzione matematica (avendo quindi una funzione continua anzichè tanti campioni). Oppure puoi addestrare un braccio robotico.

Riallego il codice del programma modificato come libreria per arduino DUE. Compila senza problemi ora però mi serve qualcuno che gentilmente lo testi.
Ditemi se ci sono problemi con il file .zip :slight_smile:

Se mi passi uno sketch che la usa posso provarla io.
Ti chiedo lo sketch perché come detto non sapendo cosa fa una rete neurale, non so come usarla :sweat_smile:

Prova con questo quando hai un po' di tempo:

#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.

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

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.

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

Non capisco questo:

if(digitalRead(LearnPin==1))

Siccome definisci LearnPin come 4,
il codice sarebbe:

if(digitalRead(4==1))

Ma 4 è diverso da 1, quindi dovrebbe leggere il pin 0 (0 è false).
O mi sfugge qualcosa?

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