Arduino-Nano y redes neuronales artificiales: 5 pasos (con fotos)

Arduino-Nano y redes neuronales artificiales: 5 pasos (con fotos)

Tabla de contenido:

Anonim

Hola amigos, Aquí hay una implementación de redes neuronales artificiales (ANN) en el tablero Arduino Nano, que he hecho recientemente.

Los pasos a continuación explicarán cómo se puede entrenar un programa ANN de muestra para aprender el Tabla de verdad XOR Salidas muy eficientemente.

Esto se puede ampliar aún más a cualquier tabla de verdad.

Gracias a estos recursos, me he referido y son increíblemente fáciles de aprender.

Revise estos para su lectura!

  • ANN para Arduino:

Suministros:

Paso 1: Componentes Requeridos

  • Arduino Nano
  • Módulo de pantalla OLED
  • Tablero de arranque del módulo de palanca de mando (eje analógico de 2 ejes)

La razón por la que elegí Arduino Nano es que se adapta mejor al diseño compacto

Algunos detalles a continuación, desde el sitio de Arduino >>

El Arduino Nano es un tablero pequeño, completo y fácil de utilizar basado en el ATmega328 (Arduino Nano 3.x). Tiene más o menos la misma funcionalidad del Arduino Duemilanove, pero en un paquete diferente. Solo le falta un conector de alimentación de CC y funciona con un cable USB Mini-B en lugar de uno estándar.

Paso 2: Las conexiones para pantalla y entradas (joystick)

Módulo Oled

Esto es muy fácil de conectar y hay una amplia gama de bibliotecas disponibles desde requisitos de visualización simples hasta avanzados.

  • http://github.com/olikraus/u8glib

Módulo JoyStick

Se elige este tipo de control de entrada porque funciona bien con la navegación y selección de elementos del menú.

  • http://www.arduino.cc/en/Tutorial/JoyStick

Paso 3: Creación del menú para la entrada de muestra para la red neuronal

Datos de entrenamiento y entradas del usuario

Como se mencionó anteriormente, usamos la tabla XOR Truth anterior como datos de entrenamiento y probamos el programa usando estas entradas para verificar las salidas reales con estas salidas.

  • El usuario debe poder suministrar (0,0), (1,0), (0,1) y (1,1) desde el dispositivo que estamos construyendo.

Creación del menú de Oled

El menú se crea utilizando el programa estándar de los ejemplos en el Editor de Arduino, disponible una vez que se instala la biblioteca u8glib. Aquí está el menú en uso en la imagen.

  • Establecer entrada de muestra El elemento de menú es el que el usuario selecciona para enviar entradas (enumeradas arriba) al programa de red neuronal

Paso 4: El programa de la red neuronal artificial en Arduino

NOTA: NO ES EL PROGRAMA ACTUAL !! A CONTINUACIÓN SE MUESTRA DE hobbizine, PARA REFERENCIA Sólo REF: hobbizine -> ¡Un gran artículo para aprender la programación de ANN en Arduino! #incluir / ************************************************** ***************** * Configuración de red - personalizada por red ************************** **************************************** / const int PatternCount = 10; const int InputNodes = 7; const int HiddenNodes = 8; const int OutputNodes = 4; const float LearningRate = 0.3; Flota constante Momentum = 0.9; const float InitialWeightMax = 0.5; const float Success = 0.0004; entrada de byte const PatternCount InputNodes = {{1, 1, 1, 1, 1, 1, 0}, // 0 {0, 1, 1, 0, 0, 0, 0}, // 1 { 1, 1, 0, 1, 1, 0, 1}, // 2 {1, 1, 1, 1, 0, 0, 1}, // 3 {0, 1, 1, 0, 0, 1, 1}, // 4 {1, 0, 1, 1, 0, 1, 1}, // 5 {0, 0, 1, 1, 1, 1, 1}, // 6 {1, 1, 1, 0, 0, 0, 0}, // 7 {1, 1, 1, 1, 1, 1, 1}, // 8 {1, 1, 1, 0, 0, 1, 1} // 9 }; const byte Target PatternCount OutputNodes = {{0, 0, 0, 0}, {0, 0, 0, 1}, {0, 0, 1, 0}, {0, 0, 1, 1}, {0, 1, 0, 0}, {0, 1, 0, 1}, {0, 1, 1, 0}, {0, 1, 1, 1}, {1, 0, 0, 0}, {1, 0, 0, 1}}; / ************************************************** ***************** * Finalizar la configuración de red ***************************** ************************************* / int i, j, p, q, r; int ReportEvery1000; int RandomizedIndex PatternCount; Ciclo de entrenamiento largo; flotar Rando; error de flotación; flotar Accum; flotar Oculto Nodos ocultos; Salida flotante OutputNodes; flotar HiddenWeights InputNodes + 1 HiddenNodes; float OutputWeights HiddenNodes + 1 OutputNodes; float HiddenDelta HiddenNodes; float OutputDelta OutputNodes; flotar ChangeHiddenWeights InputNodes + 1 HiddenNodes; float ChangeOutputWeights HiddenNodes + 1 OutputNodes; void setup () {Serial.begin (9600); randomSeed (analogRead (3)); ReportEvery1000 = 1; para (p = 0; p <PatternCount; p ++) {RandomizedIndex p = p; }} void loop () {/ ****************************************** ************************ * Inicializar HiddenWeights y ChangeHiddenWeights ********************* ********************************************* / para (i = 0; i <HiddenNodes; i ++) {para (j = 0; j <= InputNodes; j ++) {ChangeHiddenWeights j i = 0.0; Rando = float (random (100)) / 100; HiddenWeights j i = 2.0 * (Rando - 0.5) * InitialWeightMax; }} / *********************************************** ******************* * Inicializar OutputWeights y ChangeOutputWeights ************************** **************************************** / for (i = 0; i <OutputNodes; i ++) {para (j = 0; j <= HiddenNodes; j ++) {ChangeOutputWeights j i = 0.0; Rando = float (random (100)) / 100; OutputWeights j i = 2.0 * (Rando - 0.5) * InitialWeightMax; }} Serial.println ("Resultados iniciales / no entrenados:"); aTerminal (); / ************************************************** ************************************************************* ************************************ / para (TrainingCycle = 1; TrainingCycle <2147483647; TrainingCycle ++) { / ************************************************** ***************** * Aleatorizar el orden de los patrones de entrenamiento *************************** *************************************** / for (p = 0; p <PatternCount; p ++) {q = aleatorio (PatternCount); r = índice aleatorio p; RandomizedIndex p = RandomizedIndex q; Índice aleatorio q = r; } Error = 0.0; / ************************************************** ***************** * Ciclo a través de cada patrón de entrenamiento en el orden aleatorio *********************** ******************************************* / para (q = 0; q <PatternCount; q ++) {p = RandomizedIndex q; / ************************************************** ***************** * Calcular las activaciones de capas ocultas **************************** ************************************** / for (i = 0; i <HiddenNodes; i ++) {Accum = HiddenWeights InputNodes i; para (j = 0; j <InputNodes; j ++) {Acumulación + = Entrada p j * HiddenWeights j i; } Oculto i = 1.0 / (1.0 + exp (-Accum)); } / ************************************************ ****************** * Calcular las activaciones de la capa de salida y calcular los errores ************************ ****************************************** / para (i = 0; i <OutputNodes; i ++) {Accum = OutputWeights Nodos ocultos i; para (j = 0; j <HiddenNodes; j ++) {Accum + = Oculto j * OutputWeights j i; } Salida i = 1.0 / (1.0 + exp (-Accum)); OutputDelta i = (Target p i - Output i) * Output i * (1.0 - Output i); Error + = 0.5 * (Objetivo p i - Salida i) * (Objetivo p i - Salida i); } / ************************************************ ****************** * Backpropagate errores a la capa oculta *************************** **************************************** / for (i = 0; i <HiddenNodes; i ++) {Acumulación = 0.0; para (j = 0; j <OutputNodes; j ++) {Accum + = OutputWeights i j * OutputDelta j; } HiddenDelta i = Acumulación * Oculto i * (1.0 - Oculto i); } / ************************************************ ****************** * Actualizar interior -> Pesos ocultos ************************ ****************************************** / para (i = 0; i <HiddenNodes; i ++) {ChangeHiddenWeights InputNodes i = LearningRate * HiddenDelta i + Momentum * ChangeHiddenWeights InputNodes i; HiddenWeights InputNodes i + = ChangeHiddenWeights InputNodes i; para (j = 0; j <InputNodes; j ++) {ChangeHiddenWeights j i = LearningRate * Input p j * HiddenDelta i + Momentum * ChangeHiddenWeights j i; HiddenWeights j i + = ChangeHiddenWeights j i; }} / *********************************************** ******************* * Actualización oculta -> Pesos de salida *********************** ******************************************* / para (i = 0; i <OutputNodes; i ++) {ChangeOutputWeights HiddenNodes i = LearningRate * OutputDelta i + Momentum * ChangeOutputWeights HiddenNodes i; OutputWeights Nodos ocultos i + = ChangeOutputWeights Nodos ocultos i; para (j = 0; j <HiddenNodes; j ++) {ChangeOutputWeights j i = LearningRate * Hidden j * OutputDelta i + Momentum * ChangeOutputWeights j i; OutputWeights j i + = ChangeOutputWeights j i; }}} / ********************************************** ******************** * Cada 1000 ciclos envían datos al terminal para su visualización ******************** ********************************************** / ReportEvery1000 = ReportEvery1000 - 1; if (ReportEvery1000 == 0) {Serial.println (); Serial.println (); Serial.print ("TrainingCycle:"); Serial.print (TrainingCycle); Serial.print ("Error ="); Serial.println (Error, 5); aTerminal (); if (TrainingCycle == 1) {ReportEvery1000 = 999; } else {ReportEvery1000 = 1000; }} / *********************************************** ******************* * Si la tasa de error es menor que el umbral predeterminado, finalice ****************** ************************************************/ Si (Error <Success) break; } Serial.println (); Serial.println (); Serial.print ("TrainingCycle:"); Serial.print (TrainingCycle); Serial.print ("Error ="); Serial.println (Error, 5); aTerminal (); Serial.println (); Serial.println (); Serial.println ("Training Set Solved!"); Serial.println ("--------"); Serial.println (); Serial.println (); ReportEvery1000 = 1; } void toTerminal () {for (p = 0; p <PatternCount; p ++) {Serial.println (); Serial.print ("Patrón de entrenamiento:"); Serial.println (p); Serial.print ("Entrada"); para (i = 0; i <InputNodes; i ++) {Serial.print (Entrada p i, DEC); Serial.print (""); } Serial.print ("Target"); para (i = 0; i <OutputNodes; i ++) {Serial.print (Target p i, DEC); Serial.print (""); } / ************************************************ ****************** * Calcular activaciones de capas ocultas *************************** *************************************** / for (i = 0; i <HiddenNodes; i ++) {Accum = HiddenWeights InputNodes i; para (j = 0; j <InputNodes; j ++) {Acumulación + = Entrada p j * HiddenWeights j i; } Oculto i = 1.0 / (1.0 + exp (-Accum)); } / ************************************************ ****************** * Calcular las activaciones de la capa de salida y calcular los errores ************************ ****************************************** / para (i = 0; i <OutputNodes; i ++) {Accum = OutputWeights Nodos ocultos i; para (j = 0; j <HiddenNodes; j ++) {Accum + = Oculto j * OutputWeights j i; } Salida i = 1.0 / (1.0 + exp (-Accum)); } Serial.print ("Salida"); para (i = 0; i <OutputNodes; i ++) {Serial.print (Salida i, 5); Serial.print (""); }}}

Paso 5: ¡¡ANN en acción en Arduino Nano !!

Aquí está la demostración de ANN para los datos de entrenamiento de XOR en acción.

¡Feliz programación!