Robot inteligentes: un robot que aprende

por Tomás de Camino Beck

Si los robots tuvieran que tener todo pre-programado sería un problema. Simplemente no podrían adaptarse a cambios, un “programador” tendría que cambiar el código para que el robot funcione cada vez que el entorno cambie. La forma de resolverlo es permitiendo que el robot aprenda y la inteligencia artificial es una alternativa necesaria si queremos que los robots no solo hagan lo que nosotros necesitemos que hagan, sino que nos ayuden a buscar incluso una mejor solución.

Con el RobotKit podemos construir un robot inteligente, es decir un robot que aprende sólo una tarea. Para lograrlo utilizaremos una red neuronal muy simple, tan simple que solamente tiene una neurona, y la estrategia de aprendizaje del robot es lo que se conoce como aprendizaje reforzado.

Aprendizaje Reforzado

Cuando los bebes aprenden a caminar, la forma que aprenden es por ensayo y error, intentamos caminar, y si lo hacemos mal caemos (retroalimentación negativa), eso refuerza el hecho de que así no es como se camina. Por el contrario cuando logramos avanzar, entonces refuerza lo que estamos haciendo bien (retroalimentación positiva). El bebé simplemente logra, mediante este tipo de aprendizaje a coordinar sus movimientos para lograr un objetivo que tiene muy claro.

En nuestro robot lo que queremos lograr es que camine, utilizando un sensor de luz, de forma dirigida hacia la luz. Solamente tendrá dos tipos de movimiento: avanzar hacia adelante, y rotar hacia un lado. Queremos que aprenda a moverse hacia adelante cuando su movimiento lo acerque a la luz, y a girar por un tiempo determinado cuando no lo haga. El reforzamiento será de la siguiente manera:

  1. Si el movimiento mejora la luz, con respecto a su posición anterior, entonces se premia
  2. Si el movimiento resulta en una posición de menos luz, entonces se penaliza el movimiento para que no lo vuelva a hacer.

Inicialmente el robot no tendrá coordinación entre sus movimientos y el objetivo, y a través de aprendizaje reforzado, irá aprendiendo a coordinarlos para lograra de la forma más efectiva si movimiento hacia la luz.

Pero, ¿cómo aprende? El resultado del aprendizaje es almacenado como números reales en un pequeño código en la computadora. Esos números, se van ajustando a medida que el aprendizaje avanza. Ese pequeño código corresponde a lo que se conoce como Red Neuronal.

Redes Neuronales

Antes de hablar de redes neuronales, hablemos del sistema nervisos y de cerebro. El sistema nervisos está constituido por un tipo muy particular de células que se les llama neuronas. Una neurona es una celula que transmite impulsos nervisos, esos impulsos viajan dentro de la neurona y son transmitidos a atras neuronas. Hay neuronas concetadas a “sensores” como nuestros ojos, y las neuronas también accionan “actuadores” como nuestros músculos.

Una neurona típica se ve así:

Tomado de Wikimedia

La neurona recibe información a través de las dendritas. La señal recibida, viaja a través del axon, como un potencial electro-químico, para luego llegar a la terminal del axón y transmitir a músculos o otras neuronas a través de neuro-transmisores.

EL cerebro está constituido por miles de millones de estas neuronas. Los rotíferos son los animales con menos neuronas (unas 200). Cuando aprendemos, se establecen conexiones particulares entre las neuronas, y a medida que fijamos ese aprendizaje, se van formando mayor cantidad de células de mielina (ver foto), que hacen que la transmisión de impulsos nerviosos se refuerce. Es decir se van reforzando ciertas rutas en el cerebro de transmisión de impulsos.

Tomando esa idea, varios científicos por allí de 1948 (Turing 1948, McCullog y Pitts 1943), se les ocurrió construir una idea similar como un modelo matemático. Es decir construir una red de neuronas artificiales como formulas matemáticas que transmiten números, y cuyos coeficientes, se van modificando, casi como células de mielina, para indicar como fluye la información por la red.

La unidad fundamental de esas redes neuronales, se le conoce como percetrón. Un perceptrón es básicamente un modelo matemático de una neurona. Veamos ahora como es.

Perceptrón

El perceptrón es un algoritmo basado en el funcionamiento de una neurona. fue desarrollado pro primera vez en 1957 por Frank Rosenblatt. En esa época no existína las computadoras que conocemos hoy, y para que tengan una idea, este es un preceptrón de finales de los 50s (Mark I),

Perceptrón Mark I

Esta máquina costó millones de dolares de hoy, y represetna el trabajo de muchos investigadores. En esa época se buscaba sobre todo hacer reconocimiento de imágenes. Vean por ejemplo este extracto de un documental de inicios de los 60s con el perceptrón,

Para nuestra suerte, el pequeño controlador que está en el centro del RobotKit, un S4A EDU de la empresa Dagu, es un simplemente un pequeño computador con un micro-controlador ATmega 328P, que solamente cuesta unos pocos dolares y es mucho miles de veces más poderoso que el Perceptrón Mark I, y por eso es posible programar perceptrones dentro de esa pequeña computadora y en nuestro robot.

EL perceptrón tiene 3 elementos básicos que copia de una neurona como se muestra en el siguiente esquema,

Estos son:

  1. Recibir información
  2. Integrara la información recibida y decidir transmitirla
  3. Comunicar a actuadores u otras neuronas

Nosotros queremos que nuestro robot aprenda a seguir la luz con solamente un sensor de luz. Vamos a construir un perceptrón que tome dos entradas:

  1. la luz percibida (un valor entre 0 y 1023) antes del movimiento
  2. la luz percibida después del movimiento

El esquema de nuestro perceptrón se vería así:

Entonces:

  1. las entradas son los valores de luz anterior, luz después y on tercero que marcamos como bias, que tiene siempre el valor de -1 (esto para evitar valores 0 de entradas)
  2. Se hace una suma ponderada de las entradas, es decir, luz anterior x w1 + luz después x w2 + bias x w3.
  3. Se usa la función de activación que determina que cuando la suma ponderada (del punto anterior) es mayor a algún valor entonces que comunique 1, de lo contrario -1. En este caso 1 para nosotros representa movimiento hacia la luz, y -1 que no se mueve hacia la luz.

Eso es todo el perceptrón!

El aprendizaje consiste en calcular los valores w1, w2 y w3 para que el perceptrón nos de como resultado 1 o -1 con el patrón que nosotros deseamos en las entradas. Para eso se ejecuta el algoritmo de aprendizaje qie se le conoce como descenso de gradiente, no voy a dar detalles sino simplemente explicarlo de manera coneptual.

Algoritmo de Aprendizaje

El algortimo es el siguiente:

  1. Leer entradas indicadas (luz ahora y luz anterior) y aplicar los pasos anteriores. Este paso se le conoce como forward. Básicamente entra la señal y dispara el perceptrón para producir un resultado ya sea 1 o -1.
  2. Ejecutar el movimiento del robot, es decir moverse hacia adelante si el resultado fue 1, y rotar a la izquierda si el resultado es -1.
  3. Medir la luz nuevamente y evaluar so el resultado era el esperado, es decir se movió a la luz cuando el perceptrón indicó 1 o no. La retroalimentación positiva se marca con un 1, es decir lo hizo bien, y la negativa con un -1, es decir se castiga. Se ajustan los pesos con esos valores (acá no doy detalles pero es básicamente ajuste estadístico de funciones). Este paso se le conoce como train.
  4. comenzar de nuevo en el punto 1.

De esa manera, por cada iteración del robot (loop en el código de Arduino), el robot va ajustando los pesos w1,w2 y w3, y de esa manera va aprendiendo.

Código

Acá el código que iremos explicando línea a línea,

1     #include <RobotKit.h>
2 #include <Perceptron.h>
3     perceptron brain(3);
4     int currentLight = 0, lightBefore = 0;
5     void setup()
6 {
7 setMotors();
8 setSensor(A0);
9 // inicia el aleatorio
10 randomSeed(readSensor(A0));
11 brain.randomize();
12 brain.setTraining(0.0008);
13 delay(2000);
14 }
15    void loop()
16 {
17 lightBefore = currentLight;
18 currentLight = analogRead(A0);
19 brain.inputs[0] = lightBefore;
20 brain.inputs[1] = currentLight;
21 int res = brain.feedForward();
22 if (res > 0) {
23 forward(150, 100);
24 } else {
25 pivotLeft(200,50);
26 }
27 int obs = eval(lightBefore, currentLight);
28 brain.train(obs,res);
29    }
//***** función de evaluación******
30    int eval(int val1, int val2) {
31 if (val1 >= val2) {
32 return 1;
33 }
34 else {
35 return -1;
36 }
37 }
  • Las líneas 1 y2 simplemente cargan las librerías del RobotKit y del Perceptrón
  • La línea 3 prepara un perceptrón de 3 entradas que llamamos brain
  • Línea 4 Declaramos las variables currentLight y lightBefore para almacenar la información de los sensores
  • Línea 7, prepara los motores del robot
  • linea 8 Prepara el sensor conectado al pin A0
  • Linea 10, prepara el generador de números aleatorios
  • línea 11, asigna los pesos iniciales de nuestro perceptrón de forma aleatoria
  • Línea 12, define la velocidad de parendizaje del perceptrón, valores cercanos a1 hace que aprenda rápido, pero también que olvide rápido. Valores pequeños hace que aprenda lento pero seguro.
  • Línea 17, almacena el valor de luz anterior leido
  • Linea 18, lee el nuevo valor del sensor de luz
  • Líneas 19 y 20, pasa los valores a las entradas del perceptrón
  • Línea 21, dispara el perceptrón para que nos indique si 1 o -1 para hacer el movimiento
  • De las líneas 22 a 26, si el perceptrón nos indica 1, entonces que se mueva hacia adelante. Si es -1 entonces que de vuelta a la izquierda.
  • Línea 27, ese ejecuta la porción de código que está en las líneas 30 a la 37. Evalua si lo observado, es decir si la lectura nueva de luz es mejor que la anterior. En ese caso devuelve el valor 1, de lo contrario el valor -1.
  • Línea 28, le indica al perceptrón que corrija el error, es decir si dio 1, cuando debió decir -1 o viceversa. Para hacerlo, la función train, re-calcula los pesos, basado en que tan grande fue el error.

El código lo pueden descargar directamente acá.

El Robot Inteligente

En el robot, solamente ocupamos un sensor de luz conectado al pin A0 de la placa. Ajustar el sensor en la parte delantera del robot, con el fotoresistor apuntando hacia adelante, como se ve en la foto,

Cargar el código al robot, y colocar el robot en un lugar donde haya un gradiente de luz, es decir, una fuente de luz intensa. Dejar el robot y en un par de minutos aprenderá y llegará a la luz. Luego pueden mover la fuente de luz y verán como el robot se re-acomoda (siempre rotando solo a la izquierda), para dirigirse a la luz. El comportamiento que aprende es muy similar al del ejercicio del robot bacteria, sin embargo en este caso el robot aprende sólo este comportamiento.

Veamos el video, del robot funcionando,

Como ven aprende muy rápido!, y luego sigue la luz sin problema…

El robot lo que hace a fin de cuentas es solucionar una manera de moverse que le permiten caminar hacia un gradiente de luz, donde si detecta que las condiciones de luz mejoran, camina hacia adelante, y si ve que no mejoran tiende a girar hasta que en un posición en el giro las condiciones mejoren, para luego continuar hacia adelante.

Retos

  • pensar en otros tipos de movimiento para que el robot aprenda
  • Agregar un segundo sensor de luz, para que utilice la diferencia entre sensores para dirigirse a la luz
  • Que aprenda otras cosas utilizando otros sensores.

RobotKit un robot para todos

Show your support

Clapping shows how much you appreciated FunCostaRica’s story.