python - recurrente - ¿Cómo hacer que los organismos virtuales aprendan usando redes neuronales?
redes neuronales convolucionales python (6)
Estoy haciendo una simulación de aprendizaje simple, donde hay múltiples organismos en la pantalla. Se supone que deben aprender a comer, utilizando sus redes neuronales simples. Tienen 4 neuronas, y cada neurona activa el movimiento en una dirección (es un plano 2D visto desde la perspectiva del ave, por lo que solo hay cuatro direcciones, por lo tanto, se requieren cuatro salidas). Su única entrada son cuatro "ojos". Solo un ojo puede estar activo en ese momento, y básicamente sirve como un puntero al objeto más cercano (ya sea un bloque de alimentos verde u otro organismo).
Por lo tanto, la red se puede imaginar así:
Y un organismo se ve así (tanto en teoría como en la simulación real, donde realmente son bloques rojos con sus ojos a su alrededor):
Y así es como se ve todo (esta es una versión antigua, donde los ojos todavía no funcionaban, pero es similar):
Ahora que ya describí mi idea general, déjenme llegar al corazón del problema ...
Inicialización | Primero, creo algunos organismos y comida. Entonces, todos los 16 pesos en sus redes neuronales se establecen en valores aleatorios, como este: weight = random.random () * threshold * 2. El umbral es un valor global que describe la cantidad de entrada que cada neurona necesita para activar ("disparar"). Por lo general, se establece en 1.
Aprendiendo | Por defecto, los pesos en las redes neuronales se reducen en un 1% en cada paso. Pero, si algún organismo realmente logra comer algo, la conexión entre la última entrada y salida activa se fortalece.
Pero, hay un gran problema. Creo que este no es un buen enfoque, ¡porque en realidad no aprenden nada! Solo aquellos que tuvieron sus pesos iniciales aleatoriamente establecidos para ser beneficiosos tendrán la oportunidad de comer algo, y solo ellos tendrán sus pesas fortalecidas. ¿Qué hay de aquellos que tenían sus conexiones mal configuradas? Ellos solo morirán, no aprenderán.
¿Cómo evito esto? La única solución que viene a la mente es aumentar / disminuir aleatoriamente los pesos, de modo que, eventualmente, alguien obtenga la configuración correcta y coma algo por casualidad. Pero creo que esta solución es muy cruda y fea. ¿Tienes alguna idea?
EDIT: Gracias por tus respuestas! Cada uno de ellos fue muy útil, algunos fueron más relevantes. He decidido usar el siguiente enfoque:
- Establezca todos los pesos en números aleatorios.
- Disminuya los pesos a lo largo del tiempo.
- A veces aumenta o disminuye aleatoriamente un peso. Cuanto más exitosa sea la unidad, menos cambiarán sus pesos. NUEVO
- Cuando un organismo come algo, aumente el peso entre la entrada correspondiente y la salida.
¿Cómo quieres que aprenda? No te gusta el hecho de que los organismos sembrados aleatoriamente mueran o prosperen, pero la única vez que proporcionas retroalimentación a tu organismo es si obtienen alimentos al azar.
Vamos a modelar esto como caliente y frío. Actualmente, todo se retroalimenta "frío", excepto cuando el organismo está justo encima de los alimentos. Entonces, la única oportunidad de aprender es correr accidentalmente sobre la comida. Puede ajustar este ciclo para proporcionar una retroalimentación más continua si lo desea. Retroalimentación de respuesta si hay movimiento hacia la comida, frío si se aleja.
Ahora, la desventaja de esto es que no hay información para nada más. Solo tienes una técnica de aprendizaje de búsqueda de comida. Si desea que sus organismos encuentren un equilibrio entre el hambre y algo más (por ejemplo, evitar la sobrepoblación, el apareamiento, etc.), probablemente sea necesario repensar todo el mecanismo.
Como lo mencionó Mika Fischer, esto suena similar a los problemas de la vida artificial, así que esa es una avenida que podrías mirar.
También suena un poco como si estuvieras tratando de reinventar el Aprendizaje de refuerzo . Yo recomendaría leer a través de Refuerzo de aprendizaje: una introducción , que está disponible gratuitamente en formato HTML en ese sitio web, o que se puede comprar en formato de árbol muerto. El código de ejemplo y las soluciones también se proporcionan en esa página.
El uso de redes neuronales (y otros aproximadores de funciones) y técnicas de planificación se discute más adelante en el libro, así que no se desanime si las cosas iniciales parecen demasiado básicas o no aplicables a su problema.
Creo que Polyworld presenta un ejemplo más complejo de lo que estás haciendo.
También puede ver la presentación de Google Tech Talks desde 2007: http://www.youtube.com/watch?v=_m97_kL4ox0
Sin embargo, la idea fundamental es adoptar un enfoque evolutivo dentro de su sistema: usar pequeñas mutaciones aleatorias combinadas con cruzamiento genético (como la forma principal de diversificación) y seleccionar individuos que sean "mejores" para sobrevivir en el medio ambiente.
Esto es similar a los problemas con tratar de encontrar un mínimo global , donde es fácil quedar atrapado en un mínimo local. Considere tratar de encontrar el mínimo global para el perfil a continuación: coloca la pelota en diferentes lugares y sígala a medida que rueda cuesta abajo hasta el mínimo, pero dependiendo de dónde la coloque, puede quedarse atascado en un chapuzón local.
Es decir, en situaciones complicadas, no siempre se puede llegar a la mejor solución desde todos los puntos de partida utilizando pequeños incrementos de optimización. Las soluciones generales a esto son fluctuar los parámetros ( es decir , los pesos, en este caso) más vigorosamente (y generalmente reducir el tamaño de las fluctuaciones a medida que avanza la simulación, como en el recocido simulado), o simplemente darse cuenta de que un montón de los puntos de partida no van a ir a ninguna parte interesante.
Existen varios algoritmos que se pueden usar para optimizar los pesos en una red neuronal, el más común es el algoritmo de retropropagación .
Al leer tu pregunta, deduzco que estás tratando de construir bots de redes neuronales que buscarán comida. La forma de lograr esto con la retropropagación sería tener un período inicial de aprendizaje, donde los pesos inicialmente se establecen aleatoriamente (como lo hace) y se refinan gradualmente mediante el algoritmo de retropropagación hasta que alcanzan un nivel de rendimiento con el que están satisfechos. En ese punto, puede evitar que aprendan y les permita divertirse libremente en la llanura.
Sin embargo, creo que puede haber algunos problemas con el diseño de su red. En primer lugar, si solo hay 1 ojo activo en cualquier momento, tendría más sentido tener solo un nodo de entrada y realizar un seguimiento de la orientación de otra manera (si lo estoy entendiendo correctamente). Simplemente, si solo hay un ojo activo y cuatro acciones posibles (adelante, atrás, izquierda, derecha), entonces las entradas de los ojos inactivos (presumiblemente cero) no influirían en la decisión de salida, de hecho, sospecho que los pesos para cada uno la entrada a todas las salidas convergería, esencialmente duplicando la misma función. Además, aumenta innecesariamente la complejidad de la red y aumenta el tiempo de aprendizaje. En segundo lugar, no necesita tantas neuronas de salida para representar todas las acciones posibles. Como lo has descrito allí, tu salida sería {1,0,0,0} = derecha, {0,1,0,0} = izquierda y así sucesivamente. Dependiendo del tipo de neurona modelada, esto se puede hacer con 2 o incluso 1 neurona de salida. Si usa una neurona binaria (cada salida es 1 o 0), haga algo como {0,0} = atrás, {1,1} = adelante, {1,0} = izquierda, {0,1} = derecha . Usando una neurona de función sigmoidal (la salida puede ser un número real de 0..1), podrías hacer {0} = atrás, {0.33} = izquierda, {0.66} = derecha, {1} = adelante.
Puedo ver un montón de problemas potenciales.
Antes que nada, no tengo claro el algoritmo que actualiza tus pesas. Me gusta la reducción del 1% como concepto, parece que estás tratando de descontar los recuerdos distantes, lo cual es bueno en principio, pero el resto probablemente no sea suficiente. Necesita ver algunos de los algoritmos de actualización estándar como backpropagation, pero eso es sólo el comienzo, porque ...
... Solo le está dando crédito a su red por la última etapa de comer la comida. No parece que haya ningún mecanismo directo para acercar gradualmente su red a la comida o a grupos de alimentos. Incluso tomando la direccionalidad de los ojos a su valor nominal, tus ojos son muy simples, y no hay mucha memoria a largo plazo.
Además, si su diagrama de red es preciso, probablemente no sea suficiente. Realmente desea tener una capa oculta (al menos una) entre los sensores y los actuadores, si usa algo relacionado con la retropropagación. Hay matemática detallada detrás de esa afirmación, pero se reduce a "Las capas ocultas permitirán buenas soluciones de más problemas".
Ahora, observe que muchos de mis comentarios están hablando de la arquitectura de la red, pero solo en términos generales sin decir concretamente, "Esto funcionará" o "eso funcionará". Eso es porque tampoco lo sé (aunque creo que la sugerencia de Kwatford de reforzar el aprendizaje es muy buena). A veces, puede evolucionar los parámetros de red así como las instancias de red. Una de esas técnicas es Neuroevolution of Augmenting Topologies, o "NEAT". Puede valer la pena mirar.