February 8, 2019 | Author: Javier Sacán | Category: N/A
Download Programando Redes Neuronales Artificiales Paso a Paso con Python.pdf...
Tabla de Contenido Presentación Intención de la Serie
Temas de los Libros de la Serie Requerimientos para Seguir el Libro Como Seguir este Libro Recordando el Libro Anterior Lo que Abarca este Libro El Siguiente Libro Rompiendo Paradigmas
1. Antecedentes 2. Limitantes 3. Utilidad 4. Explicación Inicial 5. Modificación para Incorporar el Sesgo 5.1. Pseudocódigo
5.2. Código en Python 6. Algoritmo Sencillo Completo 6.1. Pseudocódigo Completo
6.2. Código en Python Completo 7. ¿Por qué el Sesgo puede retrasar el aprendizaje? 8. Rompiendo el Sesgo 8.1. Pseudocódigo Cambio
8.2. Código en Python Cambio 8.3. Reflexión 9. Algoritmo Complementado para Ejercicios 9.1. Pseudocódigo Complemento
9.2. Código en Python Complemento 9.3. Pseudocódigo Completo 9.4. Código en Python Completo 10. Algoritmo para Incorporar a Proyectos 10.1. Pseudocódigo de la Función
10.2. Código en Python de la Función 11. Nuevo Paradigma del Sesgo Retroalimentación
www.fullengineeringbook.net
Serie Tutorial:
Programando Redes Neuronales Artificiales Paso a Paso con Python
2: Entendiendo el Sesgo (Analizado y Explicado con Sentido Práctico) Código Completo Sencillo en 89 líneas Código Completo Complementado en 153 líneas Código Perceptrón Entrenado en 14 líneas por: Eric Joel Barragán González
www.fullengineeringbook.net
Intención de la Serie: Con la presente Serie de Libros, pretendo compartir mi experiencia al trabajar con las Redes Neuronales Artificiales (RNA), la que adquirí al buscar su aplicación en mis proyectos y encontrarme con abundante y buen material teórico, con fórmulas matemáticas, pero poco práctico, muy laboriosos de aplicar, o simplemente ejemplos incompletos que solo mostraban resultados y no implementación; sin contar las horas para entenderlo antes de aplicarlo. Por lo que con esta Serie de Libros pretendo cubrir la parte práctica con ejemplos probados, y con cada Libro, puedas experimentar con tu propio código y comenzar a adaptarlos a tus proyectos, ya sea un robot o una aplicación para toma de decisiones. Así que me enfoco en guiar al lector que quiere experimentar con el fascinante mundo de las Redes Neuronales Artificiales codificándolo por si mismo, y que tiene dificultades para hacerlo, lo cual pretendo facilitar con al menos un ejemplo completo por Libro. Aprende haciendo. Con la Serie comienza copiando, y con tu propia experiencia, aprenderás a: 1. Evaluar las necesidades y recursos de tu Proyecto. 2. Seleccionar que tipo de RNA emplear en tu proyecto. 3. Diseñar tu propia topología de RNA. 4. Parametrizar la topología y facilitar su mejora dinámicamente, con menos recodificación. 5. Configurar tu RNA de acuerdo a tus necesidades. 6. Distinguir cuales son las partes que consumen más tiempo de cómputo, para producir una topología y código finales de desempeño eficiente, con consumo de memoria controlada. Compartiéndote comentarios de mi experiencia, que te ayuden a asimilar tu experiencia con mayor facilidad. El mundo de las RNA está en pañales, y lo que se sabe se ha aprendido a prueba y error, apoyándose un poco en teoría matemática, pero sobre todo en inspiración biológica, de las redes neuronales de los cerebros estudiados; así que si quieres aprender, creo yo, debes estar dispuesto a arriesgarte a equivocarte y tal vez hasta logres descubrir algo que nadie más ha encontrado y aportes también a este campo. Con cada Libro cubriré por lo menos un ejemplo completo, funcional y probado, explicando paso a paso el algoritmo, mostrando su pseudocódigo para facilitar su implementación en otros lenguajes, y su codificación en lenguaje Python, pues no solo es fácil de aprender y entender, además es muy utilizado, y por su claridad, ayuda a que entiendas mejor los algoritmos; por otro lado se está desarrollando una serie paralela en lenguaje C que es muy utilizado en proyectos de electrónica y PC, genera ejecutables eficientes, que en RNA de gran escala, o proyectos de recursos reducidos, es importante. www.fullengineeringbook.net
Además te recomiendo ejercicios en los que te guío, para que en tus primeros experimentos sepas que
cambiarle y donde esperar afecte, y pronto puedas refinar tu conocimiento por tu propia mano y experiencia. No necesariamente los ejemplos serán como los de los autores de cada momento de las historia de las redes neuronales, pues no es el objetivo de la Serie. Pero inspirado en estos haremos un recorrido de ejemplo en ejemplo para que puedas conocer las aportaciones principales y las incorpores a tu conocimiento y experiencia, y al terminar de recorrer esta Serie seas capaz de diseñar tus propias RNA, incorporar con mayor facilidad nuevo conocimiento y hasta realizar tus propias aportaciones en tus proyectos. Tabla de Contenido
www.fullengineeringbook.net
Temas de los Libros de la Serie: 1. Perceptrón Simple con Función Lineal 2. Perceptrón Simple con Sesgo(bias) y Función Lineal 3. Perceptrón Simple con Umbral Implícito y Función Lineal 4. Perceptrón Simple con Umbral Implícito y Función No Lineal 5. Perceptrón Monocapa con Función Sigmoide 6. Perceptrón Bicapa con Retropropagación(Backpropagation) y Función Sigmoide 7. Perceptrón Tricapa con Retropropagación(Backpropagation) y Función Sigmoide 8. Perceptrón Tricapa con Retropropagación(Backpropagation) y Función Alternas de Sigmoide 9. Perceptrón Multicapa con Ramificaciones 10. Perceptrón Multicapa con Ramificaciones Traslapadas 11. Perceptrón Multicapa con Convolución 12. Perceptrón con Aprendizaje por Refuerzo para Activar Robots 13. Perceptrón con Memoria Asociativa para Clasificación de Imágenes 14. Perceptrón para Reconocimiento de Caracteres 15. Perceptrón para Reconocimiento de Voz 16. Perceptrón para Reconocimiento de Imágenes 17. Perceptrón Evolutivo para Acelerar Aprendizaje Tabla de Contenido
www.fullengineeringbook.net
Requerimientos para Seguir el Libro: 1. Saber Programar en el Lenguaje de Tu Elección 2. Con el Lenguaje Elegido, una Máquina con Entorno de Desarrollo Listo 3. Estar Dispuesto a Experimentar 4. Nociones de Lógica Matemática 5. Haber leído y hecho los ejercicios del Libro anterior Tabla de Contenido
www.fullengineeringbook.net
Como Seguir este Libro: El Libro lo he pensado para seguir de principio a fin por aquellos que en Percetrones no tienen experiencia, muy poca, o quieren un poco de reflexión para entender mejor que es lo que está pasando, y no se quieren conformar con haber encontrado como configurar sus Perceptrones a prueba y error. Sin embargo los nombres de los Puntos que te presento son descriptivos, como para que distingas si es algo que no requieres leer y continúes con el punto siguiente. Te recomiendo codifiques tu Perceptrón en el (Punto 5), donde se encuentra en el Libro, lo estudies, principalmente poniendo atención en lo que hemos agregado de código con respecto al Sesgo, es sencillo el cambio, y en los Puntos siguientes, continuaremos con explicaciones y reflexiones. El algoritmo trae cargada la Tabla NAND; sin embargo, aunque puedes con el código que generes, cargarle las otras tablas para hacer las comparaciones, puedes esperar, y en el código complementado que te pongo más adelante, incluyo una sencilla propuesta para más fácilmente realizar las comparaciones de las diferentes tablas que ya trabajamos en el Libro anterior. Del Pseudocódigo: Sigue exactamente el mismo orden y lógica que el Código en Python, además tiene los mismos comentarios, que los encontraras comenzando con " # ". La descripción la encontraras en una letra más delgada; de manera que aunque el lenguaje Python, no sea tu elegido, te puede facilitar el entender el algoritmo y facilitar su codificación. Cuando leas en un dispositivo de pantalla pequeña, te sugiero que por lo menos cuando veas el pseudocódigo o el código, pongas la pantalla en horizontal, para que con mayor ancho, quepan las líneas completas y no pasen al siguiente renglón. Recuerda que el intérprete de Python no maneja acentos ni en los comentarios, por lo que las tablas de código, no los tienen. Tabla de Contenido
www.fullengineeringbook.net
Recordando el Libro Anterior: Partimos de un algoritmo sencillo de un Perceptrón de Una Sola Neurona, en el que identificamos, analizamos y explicamos sus partes que lo componen, como funcionan y su aportación al algoritmo; cada parte la mostramos en pseudocódigo y en Python, para después integrarlas en el código completo; analizamos y describimos cada una de las variables y constantes con las que trabaja. Identificamos las características del Algoritmo y las clasificaciones a las que es sujeto por ellas, las limitaciones que tiene, sus aportaciones y utilidad de este sencillo Algoritmo. Pusimos a prueba el Perceptrón con una serie de ejercicios, que nos permitieron poner al descubierto sus capacidades y limitaciones, incluso una forma alterna de trabajar con él, en la forma de alimentarlo, para confirmar si podía cubrir las limitaciones, además explicamos el porque de estas limitaciones con una sencilla fórmula matemática, que nos permitió entender el porque surge. Por otro lado trabajamos con ejercicios en los que Parámetro por Parámetro pusimos a prueba sus límites y aportaciones en la Configuración del Perceptrón, de que manera podemos sacarlo del ámbito de funcionamiento, cuales son estos límites y comprobamos que pasa si vamos más allá; y sobre todo de que forma pueden funcionar mejor y como podemos identificarlo para optimizar el desempeño de este sencillo Perceptrón, como base para poder analizar y entender Perceptrones más complejos. Y finalmente identificamos los momentos por los que pasa un Perceptrón hasta llegar al momento en el que termina nuestro trabajo y el Perceptrón está listo para realizar el trabajo para el que lo hemos creado, con lo que llegamos al pseudocódigo y código en Python de una Función, reducida en código y en tiempo de cómputo consumido, con respecto al Algoritmo de Aprendizaje, como ejemplo de la forma en la que un Perceptrón, ya entrenado, lo podemos integrar en nuestros proyectos. Tabla de Contenido
www.fullengineeringbook.net
Lo que Abarca este Libro: Con este Libro comenzaremos con el Tema: Rompiendo Paradigmas, una reflexión con la intención de recordarnos que hacer conscientes nuestros paradigmas, como los usamos y sus limitantes, nos permite abrir nuestra mente a las posibilidades, para ampliarlos o simplemente nos ayuden a aprender con más facilidad. Entraremos en Tema con una definición de Sesgo, de acuerdo a nuestro algoritmo, para enseguida explicar como funciona, y con fórmula, la compararemos con el algoritmo sin Sesgo. De acuerdo al algoritmo que vimos en el Libro anterior, te mostraré lo que requerimos agregar para integrarle el Sesgo, para después presentarte el algoritmo completo con Sesgo. Reflexionaremos con un sencillo ejemplo de porque el Sesgo puede hacer que el Perceptrón requiera más ciclos para aprender, o bien porque puede hacer que aprenda en menos ciclos. También haremos una reflexión fuera de foco, que nos permitirá poner al descubierto una capacidad que agrega al Perceptrón, que lo hace más poderoso. Te mostraré una propuesta de código que le puedes agregar a tu algoritmo de Perceptrón para poder hacer las comparaciones de las Tablas de Verdad en tiempo de ejecución. Y terminaremos con una propuesta de Función para un Perceptrón entrenado con Sesgo, como ejemplo de como puedes integrarlo a tus proyectos. Tabla de Contenido
www.fullengineeringbook.net
El Siguiente Libro: Trataremos lo que dio las base para la Retropropagación (backpropagation). En lugar de trabajar con un Umbral explícitamente, lo haremos implícitamente, incorporando lo que se conoce como “La Regla Delta”, que no es solo otra fórmula para hacer lo mismo; ya no solo podremos encontrar unos valores para los Pesos en el rango de convergencia, podremos aproximarnos a los óptimos, y con este aumento de precisión también aumentaremos el poder del Perceptrón. Tabla de Contenido
www.fullengineeringbook.net
Rompiendo Paradigmas: Busquemos el Paradigma que usamos para entender lo que estamos aprendiendo; conozcamos sus limites para saber hasta donde nos está frenando a avanzar el mismo Paradigma. Soñemos con pasar los límites que no nos dejar ir más halla. Ahora, para llegar a allá, ¿Que cambios necesitamos hacer en nuestra caja de herramientas?. Necesitamos tirar algunas herramientas, modificar otras, y tal vez crear algunas más que ni siquiera imaginábamos tener. Nuestros paradigmas son una maravillosa herramienta que nos permite interactuar con nuestro entorno, pueden ser o, lo que clarifica el cristal con el que miramos las cosas, o lo que enturbie este cristal y nos limite para ir más allá, para esto debemos practicar el ampliar nuestra perspectiva y poder ver más allá, solo haciéndonos conscientes de ello lo lograremos. Comencemos a reflexionar sobre la forma como estamos percibiendo el Sesgo, ya que, el como lo definimos, es el como lo usamos, y por lo tanto que podemos obtener de este. Tomando en cuenta que la forma como interpretamos lo que percibimos es lo que nos limita para potenciar los medios que usamos para cumplir nuestros objetivos, para poder ampliar el uso de estos medios debemos conocer hasta donde los estamos limitando al definirlos en si mismos. Para que quede más clara esta idea trabajemos un par de ejemplos. En Geometría Plana cuando queremos conocer una figura buscamos sus límites, en este caso, son los que definen su área, en otras palabras, diferenciamos, la parte que pertenece a la figura, de la parte que no pertenece a ella, y por nuestro concepto mismo de esto no hay duda; pero ahora vallamos a otro ejemplo, en este usaremos algo conceptual; en la naturaleza lo que encontramos lo definimos en el contexto en el que lo encontramos, con referencia a los otros elementos con los que interactúa y también por sus propias características, como un planeta, de primera intención parece claro y sin ambigüedad, y lo podríamos definir como una enorme bola de materia que gira alrededor de una estrella; sin embargo que pasa si es más pequeño, al principio solo será un planeta más pequeño, pero si aún es más pequeño, tal vez ya no lo quisiéramos nombrar planeta y le digamos planetoide, pero ¿Dónde termina uno y comienza el otro?, por tamaño, cantidad de materia, estado de la materia. Ahora esto se complica aún más cuando lo definimos por la utilidad que le damos, aún por encima del contexto en el que lo encontramos, incluso mejor digamos: por la utilidad que creemos que le podemos dar; pues el como creamos es el paradigma al que lo estamos encuadrando, limitando, le define el uso que obtenemos de el; y si tenemos aún la flexibilidad para cambiar el paradigma que le aplicamos de acuerdo a la situación, nos será más útil, como en el caso de un pedazo de madera delgado (tabla), con otros cuatro pedazos (patas), lo podemos llamar mesa si ponemos cosas encima, banco si nos sentamos en el, escalón si nos permite pisarlo para subir y bajar, y techo si nos cubre la cabeza. El punto central aquí es que para que esto ocurra por nuestra propia decisión, nos debemos hacer al hábito de hacernos conscientes de que paradigma le aplicamos a los medios, así los podemos cambiar y aumentar su utilidad. Que es lo que buscaremos hacer en este Libro con el Sesgo para el Perceptrón, primero lo definiremos, lo analizaremos y haremos ejercicios con el, para después trabajar en romper www.fullengineeringbook.net
este paradigma e intentar aumentar su utilidad formando uno nuevo. Cuando trabajamos de esta forma lo peor que puede pasar es que aunque por el momento no logremos pasar los límites, conozcamos mejor nuestras herramientas y aceleremos su aprendizaje. Tabla de Contenido
www.fullengineeringbook.net
1. Antecedentes: ¿Por qué la mayoría de los libros estudian el Perceptrón con Probabilidad y Estadística? Reconozcamos un poco de historia. Cuando Frank Rosenblatt comienza a trabajar con el Perceptrón, su intención era ilustrar algunas propiedades de los sistemas inteligentes en general, sin mayores detalles, que se desconocían de los sistemas biológicos, y creía que la conectividad que hay en los sistemas biológicos tiene un alto porcentaje de componente aleatorio, por lo que se oponía al análisis de McCulloch y Pitts, que empleaban lógica simbólica para analizar, mientras que Rosenblatt opinaba que la herramienta adecuada para su estudio, era la probabilidad y la estadística. Desde entonces la probabilidad y estadística han sido muy usadas para describir y tratar de predecir el comportamiento del Perceptrón, pues es más fácil trabajar con formulas que tratar de entender lo que hace el Perceptrón, sobretodo cuando ya estamos hablando de redes neuronales con cientos de neuronas en docenas de capas. Sin embargo, ahora sabemos que su comportamiento no es aleatorio, y aunque pueda llegar a ser muy complejo, no es más que una serie de secuencias de aproximaciones sucesivas, para interpolar los Pesos, entre los requerimientos de las diferentes combinaciones, de cada neurona, para poder dar la respuesta esperada de cada una de ellas, en el caso de ser posible con la configuración dada. Ahora, en cuanto al Sesgo, fue incorporado desde los primeros modelos, como un elemento que mejora el desempeño del Perceptrón, y lo podemos encontrar en esquemas en diferentes formas; en ocasiones se representa como un elemento único en toda la red, que alimenta a cada neurona; en otras, se representa como un elemento que tiene cada neurona, ajeno a las Entradas; y en otras más, como una Entrada más, fija en “1” o “-1”, según el algoritmo, con su propio Peso ajustable por neurona, que es como lo usamos en nuestro algoritmo. Tabla de Contenido
www.fullengineeringbook.net
2. Limitantes: El Sesgo presenta el problema de que en algunos casos en particular, incrementa el número de iteraciones requeridas para que el Perceptrón aprenda. En éste Libro reflexionaremos sobre que es lo que lo propicia. No puede ayudar al Perceptrón a aumentar su capacidad para resolver separaciones de valores de representación, más allá de en forma lineal. Tabla de Contenido
www.fullengineeringbook.net
3. Utilidad: Agrega la capacidad al Algoritmo del Perceptrón para poder resolver, superando el Umbral, cuando así se requiera, cuando todas las Entradas de la combinación tienen el valor de “0”. Agrega al Perceptrón la capacidad de resolver conflictos entre combinaciones que compiten en los ajustes de Pesos en común con direcciones contrarias. Un punto muy interesante y poco tratado sobre el que reflexionaremos también. Tabla de Contenido
www.fullengineeringbook.net
4. Explicación Inicial: Por el como en forma general usamos el Sesgo, sus elementos y características, lo definiremos como: El elemento permanente, que cada neurona artificial tiene, como Entrada adicional fija, en el caso de nuestro Algoritmo en “1”, ya que para efecto de otros algoritmos lo usan con valor en “-1”, también fijo. Al igual que las demás Entradas con su propio Peso ajustable, por medio del cual contribuye a que el Perceptrón aprenda, en especial, es indispensable para resolver combinaciones que teniendo todas las Entradas en “0” requieren el Axón en “1”. Funciona como una Entrada más, la que en lugar de alimentarse de forma externa a la neurona, simplemente siempre vale “1”, pero el Peso se considera para el cálculo del Axón como el Peso de cualquier otra Entrada, y se ajusta como cualquier otro Peso. Comparemos en fórmula el cálculo del Perceptrón sin Sesgo y con Sesgo para que acabe de quedar claro de lo que estamos hablando. Sin Sesgo 1. Suma = (Entrada[1] * Peso[1]) + (Entrada[2] * Peso[2]) + . . . + (Entrada[n] * Peso[n]) 2. Suma = (0 * Peso[1]) + (0 * Peso[2]) + . . . + (0 * Peso[n]) 3. Suma = (0) + (0) + . . . + (0) 4. Suma = 0
Con Sesgo 1. Suma = (Entrada[1] * Peso[1]) + (Entrada[2] * Peso[2]) + . . . + (1 * Peso[n]) 2. Suma = (0 * Peso[1]) + (0 * Peso[2]) + . . . + (1 * Peso[n]) 3. Suma = (0) + (0) + . . . + (Peso[n]) 4. Suma = Peso[n]
Y con esto al ser ajustable el Peso del Sesgo, si requiere superar el Umbral, se irá ajustando hasta conseguirlo, y si no, se puede mantener en valores inferiores, y no superarlo; ahora que además puede adquirir valores negativos o varias veces mayores al Umbral, y mientras cumple su función con la combinación de todas las Entradas en "0", puede apoyar a otras combinaciones a cumplir con el valor de www.fullengineeringbook.net suma, junto con los Pesos de las Entradas en "1", logrando los valores del Axón requeridos.
Tabla de Contenido
www.fullengineeringbook.net
5. Modificación para Incorporar el Sesgo: Ya que el resto del código lo vimos a detalle en el Libro anterior, solo te muestro la parte que se modifica al incorporar el Sesgo, para después pasar al algoritmo completo tanto en pseudocódigo como código en Python, y en los puntos siguientes apoyado con reflexiones y ejercicios, profundizaremos en la explicación del Sesgo. Ahora veamos las partes en el algoritmo que se modifican, y como quedan. 1. Agregamos un Peso más a definir. 2. Lo inicializamos pseudoaleatoriamente. 3. Lo mostramos para conocer con que valor comienza. 4. Lo agregamos a la fórmula del cálculo del Perceptrón. 5. Lo consideramos para ser ajustado cuando halla error en el cálculo. 6. Y mostraremos a que valor ajustó en el ciclo junto con los otros Pesos. Tabla de Contenido
www.fullengineeringbook.net
5.1. Pseudocódigo: - # Array: Pesos de Memoria - declara arreglo tipo float llamado: Pes de [3] - # Inicio Pseudo-aleatoria de los 3 Pesos - asigna a Pes[0] un valor float aleatorio entre (-1 y 1) - asigna a Pes[1] un valor float aleatorio entre (-1 y 1) - asigna a Pes[2] un valor float aleatorio entre (-1 y 1) - # Muestra en Pantalla los 3 Pesos Iniciales - muestra ("Iniciales: P0: Pes[0] P1: Pes[1] P2: Pes[2](linea) (linea)") - # Cálculo del Perceptrón para el Caso - multiplica Ent[0] por Pes[0] - multiplica Ent[1] por Pes[1] - y multiplica 1 por Pes[2] - suma resultados y los asigna a Sum - # Ajuste de Pesos con el Caso - Si Err diferente de 0: # Ajusta si hay Error - # Se realiza para cada Peso con su Entrada correspondiente - multiplica Apr por Err, y por Ent[0] - asigna el Producto más Pes[0] a Pes[0] - multiplica Apr por Err, y por Ent[1] - asigna el Producto más Pes[1] a Pes[1] - multiplica Apr por Err, y por 1 - asigna el Producto más Pes[2] a Pes[2] - # Muestra a que Pesos Ajustó - muestra ("Ajusta a: P0: Pes[0] P1: Pes[1] P2: Pes[2] (linea)"); Tabla de Contenido
www.fullengineeringbook.net
5.2. Código en Python: 4
# Array: Pesos de Memoria
5
Pes = [0.0, 0.0, 0.0]
30 # Inicio Pseudo-aleatoria de los 3 Pesos 31 Pes[0] = random.uniform(-1.0, 1.0) 32 Pes[1] = random.uniform(-1.0, 1.0) 33 Pes[2] = random.uniform(-1.0, 1.0) 35 # Muestra en Pantalla los 3 Pesos Iniciales 36 print "\033[32m Iniciales: P0:%f P1:%f P2:%f\n\n" % (Pes[0], Pes[1], Pes[2]) 50 # Calculo del Perceptron para el Caso 51 Sum = Ent[i][0] * Pes[0] + Ent[i][1] * Pes[1] + 1 * Pes[2] 52 if Sum > Ubr: # Comparacion con Umbral 53 Axn = 1 # Umbral Superado 54 else: 55 Axn = 0 # Umbral No Superado 60 # Ajuste de Pesos con el Caso 61 if Err != 0: # Ajusta si hay Error 63 # Se realiza para cada Peso con su Entrada correspondiente 64 Pes[0] += Apr * Err * Ent[i][0] 65 Pes[1] += Apr * Err * Ent[i][1] 66 Pes[2] += Apr * Err * 1 74 # Muestra a que Pesos Ajusto 75 print " Ajusta a: P0:%f P1:%f P2:%f" % (Pes[0], Pes[1], Pes[2]) Tabla de Contenido
www.fullengineeringbook.net
6. Algoritmo Sencillo Completo: A continuación te muestro el Algoritmo completo, con la misma sencillez del Libro pasado, para que lo estudies. El código trae la Tabla NAND, por ahora te sugiero esperes para cargarle las demás Tablas de Verdad, pues para facilitar este ejercicio y otros más que veremos, te incluyo el algoritmo complementado, para que en tiempo de ejecución de una forma sencilla cambies los parámetros y realices estas comparaciones, y pongas a prueba nuestras reflexiones. En tu código final puedes por supuesto omitir el Sesgo, representado por el "1", que al ser en la práctica multiplicado por su Peso o por otros elementos, no se requiere poner, pero para mayor claridad, yo lo he incluido. Tabla de Contenido
www.fullengineeringbook.net
6.1. Pseudocódigo Completo: - # Array: Pesos de Memoria - declara arreglo tipo float llamado: Pes de [3] - # Arrays: 4 Casos del Ejemplo, "Tabla NAND" - declara arreglo tipo float llamada: Ent de [4][2] - declara arreglo tipo float llamada: Sal de [4] - # Procedimiento Principal - Inicia Procedimiento Principal - # Constantes de los Parámetros Rígidos - declara variable tipo float llamada: Apr - declara variable tipo float llamada: Ubr - asigna a Apr el valor 1.0 - asigna a Ubr el valor 2.0 - # Variables de Control de Iteraciones - declara variable tipo int llamada: i - declara variable tipo int llamada: j - declara variable tipo int llamada: k - # Variables de Trabajo - declara variable tipo float llamada: Axn - declara variable tipo float llamada: Sum - declara variable tipo float llamada: Err - declara variable tipo int llamada: NEr - # Carga 4 Casos del Ejemplo, "Tabla NAND" - # Caso 1 - asigna a Ent[0][0] el valor 0 - asigna a Ent[0][1] el valor 0 - asigna a Sal[0] el valor 1 - # Caso 2 - asigna a Ent[1][0] el valor 0 - asigna a Ent[1][1] el valor 1 - asigna a Sal[1] el valor 1 - # Caso 3 - asigna a Ent[2][0] el valor 1 - asigna a Ent[2][1] el valor 0 - asigna a Sal[2] el valor 1
www.fullengineeringbook.net
- # Caso 4 - asigna a Ent[3][0] el valor 1 - asigna a Ent[3][1] el valor 1 - asigna a Sal[3] el valor 0 - # Inicio Pseudo-aleatoria de los 3 Pesos - asigna a Pes[0] un valor float aleatorio entre (-1 y 1) - asigna a Pes[1] un valor float aleatorio entre (-1 y 1) - asigna a Pes[2] un valor float aleatorio entre (-1 y 1) - # Muestra en Pantalla los 3 Pesos Iniciales - muestra ("Iniciales: P0: Pes[0] P1: Pes[1] P2: Pes[2] (linea) (linea)") - # Ciclo de Intentos - # Parámetros para 1,000 Intentos - asigna a j el valor 0 - asigna a k el valor 1,000 - Inicia Ciclo # Inicia Ciclo de Intentos - incrementa j en 1 # Incrementa Contador de Intentos - # Muestra en Pantalla Intento a Calcular - muestra ("Ciclo:j - - - - - - - - -(linea)") - # Ciclo de Casos, por Intento - asigna a NEr el valor 0 # Reinicia Contador de Errores - Inicia Ciclo # Inicia Ciclo de Casos - recorre i de 0 a 3 # Recorre los 4 Casos - # Cálculo del Perceptrón para el Caso - multiplica Ent[0] por Pes[0] - multiplica Ent[1] por Pes[1] - y multiplica 1 por Pes[2] - suma resultados y los asigna a Sum - # Comparación con Umbral - Si Sum supera a Ubr: - asigna a Axn el valor 1 - En otro caso: - asigna a Axn el valor 0 - # Cálculo de Error del Caso www.fullengineeringbook.net - a Sal (salida esperada), se resta Axn (resultante) y lo asigna a Err
- # Ajuste de Pesos con el Caso - Si Err diferente de 0: # Ajusta si hay Error - incrementa NEr en 1 # Incrementa el contador de Errores - # Se realiza para cada Peso con su Entrada correspondiente - multiplica Apr por Err, y por Ent[0] - asigna el Producto más Pes[0] a Pes[0] - multiplica Apr por Err, y por Ent[1] - asigna el Producto más Pes[1] a Pes[1] - multiplica Apr por Err, y por 1 - asigna el Producto más Pes[2] a Pes[2] - # Muestra en Pantalla Entradas y Resultado - muestra ("- Caso i E1: Ent[i][0] E2: Ent[i][1] S:Sal[i] Axn:Axn") - Si Err diferente de 0 # Si hay Error - cambia color de letra a rojo; # Muestra Errores en Rojo - muestra ("Err: Err") - cambia color de letra al anterior; # Regresa el color - # Muestra a que Pesos Ajustó - muestra ("Ajusta a: P0: Pes[0] P1: Pes[1] P2: Pes[2] (linea)"); - # Termina Ciclo de Casos - # Muestra el Número de Errores del Intento - muestra ("NEr Errores - - - - - - - - -(linea) (linea)") - # Termina Anticipadamente si no hay Errores - Si contador de errores NEr es 0 - Sale del Ciclo de Intentos - Continua Ciclo Mientras j es menor que k # Termina Ciclos de Intentos - Termina Programa # Terminación de Programa Tabla de Contenido
www.fullengineeringbook.net
6.2. Código en Python Completo: 1
# Complemento para generar aleatorios
2
import random
3 4
# Array: Pesos de Memoria
5
Pes = [0.0, 0.0, 0.0]
6 7
# Arrays: 4 Casos del Ejemplo, "Tabla NAND"
8
Ent = []
9
Sal = []
10 11 # Procedimiento Principal 12 # Constantes de los Parametros Rigidos 13 Apr = 1.0 14 Ubr = 2.0 15 16 # Carga 4 Casos del Ejemplo, "Tabla NAND" 17 # Caso 1 18 Ent += [[0,0]] 19 Sal += [1] 20 # Caso 2 21 Ent += [[0,1]] 22 Sal += [1] 23 # Caso 3 24 Ent += [[1,0]] 25 Sal += [1] 26 # Caso 4 27 Ent += [[1,1]] 28 Sal += [0] 29 30 # Inicio Pseudo-aleatoria de los 3 Pesos 31 Pes[0] = random.uniform(-1.0, 1.0) 32 Pes[1] = random.uniform(-1.0, 1.0) 33 Pes[2] = random.uniform(-1.0, 1.0) 34 35 # Muestra en Pantalla los 3 Pesos Iniciales 36 print "\033[32m Iniciales: P0:%f P1:%f P2:%f\n\n" % (Pes[0], Pes[1], Pes[2]) 37 38 # Ciclo de Intentos
www.fullengineeringbook.net
39 j = 0; k = 1000 # Parametros para 1,000 Intentos 40 while True: # Inicia Ciclo de Intentos 41 j += 1 # Incrementa Contador de Intentos 42 43 # Muestra en Pantalla Intento a Calcular 44 print "Ciclo:%d - - - - - - - - -" % (j) 45 46 # Ciclo de Casos, por Intento 47 NEr = 0 # Reinicia Contador de Errores 48 for i in range(4): # Inicia Ciclo de Casos 49 50 # Calculo del Perceptron para el Caso 51 Sum = Ent[i][0] * Pes[0] + Ent[i][1] * Pes[1] + 1 * Pes[2] 52 if Sum > Ubr: # Comparacion con Umbral 53 Axn = 1 # Umbral Superado 54 else: 55 Axn = 0 # Umbral No Superado 56 57 # Calculo de Error del Caso 58 Err = Sal[i] - Axn 59 60 # Ajuste de Pesos con el Caso 61 if Err != 0: # Ajusta si hay Error 62 NEr += 1 # Incrementa el contador de Errores 63 # Se realiza para cada Peso con su Entrada correspondiente 64 Pes[0] += Apr * Err * Ent[i][0] 65 Pes[1] += Apr * Err * Ent[i][1] 66 Pes[2] += Apr * Err * 1 67 68 # Muestra en Pantalla Entradas y Resultado 69 print ("- Caso %d E1:%d E2:%d S:%d Axn:%f Sum:%f " 70 % (i, Ent[i][0], Ent[i][1], Sal[i], Axn, Sum)), 71 if Err != 0: # Si hay Error 72 print "\033[33m", # Muestra Errores en Rojo 73 print "Err: %f\033[32m" % (Err) 74 # Muestra a que Pesos Ajusto 75 print " Ajusta a: P0:%f P1:%f P2:%f" % (Pes[0], Pes[1], Pes[2]) 76 77 # Termina Ciclo de Casos 78 79 # Muestra el Numero de Errores del Intento www.fullengineeringbook.net 80 print "%d Errores - - - - - - - - -\n" % (NEr)
81 82 # Termina Anticipadamente si no hay Errores 83 if NEr == 0: 84 break 85 86 if j >= k: # Termina Ciclos de Intentos 87 break 88 89 # Termina Programa
Como te habrás dado cuenta, ahora cargada la tabla NAND, con el Sesgo incluido, sin problema el Perceptrón puede aprender a resolverla, y si le cargaras todos los ejemplos que trabajamos en el Libro anterior, verías que resuelve también casi todos los demás, solo quedará pendiente de resolver para la tabla XOR, que ya queda fuera del alcance de este sencillo algoritmo, y ya requiere de una red de neuronas con capas, lo que cubriremos en otro Libro más adelante. Por ahora pasemos a otra reflexión. Tabla de Contenido
www.fullengineeringbook.net
7. ¿Por qué el Sesgo puede retrasar el aprendizaje?: Como sabemos, lo que realiza el Perceptrón con cada ajuste son aproximaciones sucesivas, para interpolar los valores de los Pesos, y en suma poder dar respuesta a cada combinación de Entradas con el valor del Axón requerido. Ahora supongamos un caso simplificado, el que puede ser solo parte de los requerimientos de los casos a entrenar del Perceptrón, en el que de una serie de N Entradas, se requiere que para la combinación en la que todas las Entradas están en “0” excepto las Entradas 5 y 9, y para esta combinación el Axón debe ser “0”, con rango en los Pesos entre (-1 y 1), un Umbral de “2” y un Aprendizaje de “1”; si tenemos como valores iniciales (pseudoaleatorios) para los Pesos: P5 = 0.75, y P9 = 0.75, para cada respectiva Entrada; al realizar el cálculo del Perceptrón para esta combinación, todas las demás Entradas que pudiera haber al estar en “0”, no se considerarían los Pesos y solo sumaríamos P5 + P9 para un resultado de “1.5”, lo que por estar bajo el valor del Umbral da por resultado en el Axón en “0” y al dar el resultado requerido, no es necesario ajuste alguno. Pero que pasa si además tenemos Sesgo, y de este se requiere supere el Umbral, para que cuando todas las Entradas estén en “0” pueda superar el Umbral, y al tener el valor fijo de “1”, su Peso siempre sumará para el cálculo del Perceptrón, para todas las combinaciones, por lo que en lugar de inicialmente quedar resuelto para la combinación que consideramos, con un valor inicial de “-0.99”, sumaríamos también el Peso del Sesgo, quedando: PS + P5 + P9 = -0.99 + 0.75 + 0.75 = 0.51, que a diferencia de sin Sesgo, que no requería ajuste, ahora el Sesgo demandaría se ajuste su Pesos, para llevarlo a ser mayor que el Umbral, mientras tanto como resultado, cuando sumado con los otros Pesos supere el Umbral para el otro caso, este demandará a su vez, se disminuyan los Pesos de la Entrada 5 y 9, y del Peso del Sesgo; y en esta serie de ajustes se requerirán varias iteraciones. Y por eso es que el Sesgo en ocasiones puede hacer que el Perceptrón trabaje más para encontrar los Pesos de la solución. En la siguiente tabla te muestro como podrían quedar los ciclos, marco en verde cuando para el Caso A el Sesgo requiere el aumento de su Peso, y en amarillo cuando el Caso B requiere que los Pesos disminuyan. Como también notarás, no solo depende de la dirección de los ajustes, sino también de los valores iniciales que toman los Pesos. Una situación similar puede ocurrir con cualquier combinación de Entradas, solo que a diferencia de las demás Entradas, el Peso del Sesgo siempre estará presente, por lo que puede llegar a ser más impactante. Ajuste
PS
inicial -0.99
P1
P2
suma
0.75
0.75
0.51
A 1
0.01
0.75
0.75
1.51
B 1
0.01
0.75
0.75
1.51
A 2
1.01
0.75
0.75
2.51
B 2
0.01
www.fullengineeringbook.net -0.25 -0.25 -0.49
A 3
1.01
-0.25 -0.25
0.51
B 3
1.01
-0.25 -0.25
0.51
A 4
2.01
-0.25 -0.25
1.51
B 4
2.01
-0.25 -0.25
1.51
A 5
2.01
-0.25 -0.25
1.51
B 5
2.01
-0.25 -0.25
1.51
El anterior es un ejemplo sencillo, pero lo mismo y más complicado puede pasar, mientras se teje una complicada red de ajustes para que el Perceptrón interpole los Pesos, mientras cada combinación compite con algunas otras, con las que comparte Entradas en común en “1”, pero con diferente dirección de ajuste requerido, con respecto al valor que tiene en el momento; en donde el Sesgo puede llegar a ser el principal punto de conflicto para llegar a los valores de convergencia en los Pesos. Por lo anterior ahí quien prefiere prescindir del Sesgo y soluciona con la forma en que codifica las Entradas. Por ejemplo si trabajamos con un sistema binario podríamos recorrer la representación una unidad hacia arriba y no trabajar con la combinación de Entradas de todas en “0”, que equivaldría al valor de “0”, y al recorrer la representación, solo perderíamos el último valor a representar, pero tal vez no nos afecte si es que no lo ocupamos, o si es así, lo podríamos cubrir fácilmente agregando una Entrada más a la neurona. Aunque te comento que yo no estoy de acuerdo con esta práctica, como te explico más adelante el Sesgo aporta mucho más de lo que te puede quitar haciendo que requiera hacer más iteraciones para aprender. Ahora ¿Por qué puede contribuir a favor el Sesgo y acelerar el Aprendizaje? Después de lo anterior, te será más fácil de entender, que así como puede haber combinaciones que compitan por direcciones en los ajustes de algunos Pesos en particular, también puede ocurrir lo contrario y que los ajustes tengan la misma dirección, y que en una sola iteración se lleguen a realizar varios ajustes, de diferentes combinaciones, sobre los mismos Pesos, de las Entradas en “1” en común, lo que hará que se acelere el aprendizaje. Tabla de Contenido
www.fullengineeringbook.net
8. Rompiendo el Sesgo: Si nos quedáramos con este par de apreciaciones, que acabamos de ver, muy parciales, y por lo tanto incompletas, nos podrían llevar a conclusiones equivocadas, pero al mismo tiempo, si lo hacemos con criterio nos puede llevar por caminos interesantes que nos permitirán conocer otros aspectos del Sesgo. Pues tomemos entonces lo anterior como punto de partida para explorar el Sesgo, y aún sabiendo que es incompleto y equivocado lo siguiente, supongamos por un momento que el Sesgo solo aporta cuando en el caso a resolver, tiene la combinación en la que todas las Entradas están en “0” y se requiere el Axón de “1”. ¿Para qué tener fijo el Sesgo? ¿Por qué no solo activarlo en “1” cuando todas las Entradas están en “0”, y el resto del tiempo ponerlo a “0”? después de todo hasta con el resto de las combinaciones puede llegar a ser un problema. (recordemos que es un supuesto incompleto y por lo tanto incorrecto). Así que exploremos esta proposición con la Tabla NAND en el código completo que acabamos de ver y veamos que aprendemos. Entonces modificamos el algoritmo y cuando todas las Entradas están en “0” el Peso del Sesgo valdrá “1”, y en cualquier otro caso valdrá “0”. Tabla de Contenido
www.fullengineeringbook.net
8.1. Pseudocódigo Cambio: Modificamos las lineas donde aparese el Sesgo, sustituyendo el "1" que tenía por una variable, que la pondremos en "1" para activar el Sesgo y en "0" para desactivarlo. - # Cálculo del Perceptrón para el Caso - multiplica Ent[0] por Pes[0] - multiplica Ent[1] por Pes[1] - y multiplica Sesgo por Pes[2] - suma resultados y los asigna a Sum - # Se realiza para cada Peso con su Entrada correspondiente - multiplica Apr por Err, y por Ent[0] - asigna el Producto más Pes[0] a Pes[0] - multiplica Apr por Err, y por Ent[1] - asigna el Producto más Pes[1] a Pes[1] - multiplica Apr por Err, y por Sesgo - asigna el Producto más Pes[2] a Pes[2]
Ahora insertamos lo siguiente, justo en donde está la linea que dice: # Cálculo del Perceptrón para el Caso, pues debe de ir antes de lo que acabamos de modificar. - # Sesgo Flexible - Si (la suma de las Entradas) igual a 0: - asigna a Sesgo el valor 1 - En otro caso: - asigna a Sesgo el valor 0 Tabla de Contenido
www.fullengineeringbook.net
8.2. Código en Python Cambio: Modificamos la linea 51 y la 66, para que quede como sigue. Sustituyendo el "1" que tenía por una variable, que la pondremos en "1" para activar el Sesgo y en "0" para desactivarlo. 50 # Calculo del Perceptron para el Caso 51 Sum = Ent[i][0] * Pes[0] + Ent[i][1] * Pes[1] + Sesgo * Pes[2] 63 # Se realiza para cada Peso con su Entrada correspondiente 64 Pes[0] += Apr * Err * Ent[i][0] 65 Pes[1] += Apr * Err * Ent[i][1] 66 Pes[2] += Apr * Err * Sesgo
Ahora insertamos el siguiente código en la linea 50, pues debe de ir antes del código que acabamos de modificar. 50 # Sesgo Flexible 51 if (Ent[i][0] + Ent[i][1]) == 0: 52 Sesgo = 1 # Sesgo Activado 53 else: 54 Sesgo = 0 # Sesgo Desactivado 55 Tabla de Contenido
www.fullengineeringbook.net
8.3. Reflexión: Lo primero que notaremos es que sí, efectivamente el Peso del Sesgo adquiere el valor necesario para superar el Sesgo y resuelve para esta combinación, PERO, solo para esta combinación. ¿Qué pasó? Pues que además de resolver el Sesgo la combinación con todas las Entradas en “0”, hace algo más, que es otra aportación muy importante, pues esta otra situación por la que las otras combinaciones no pueden ser resueltas, es por un conflicto irreconciliable, por lo menos en estas condiciones, PERO, ¿Qué está resolviendo el Sesgo? Este conflicto se da, porque mientras la combinación con las dos Entradas en “1” requiere el Axón en “0”, y sus Pesos deben sumar menos de “2”, por otro lado tenemos las otras dos combinaciones, con Entradas “1, 0” y “0, 1”, y ambas requieren el Axón en “1”, por lo que los valores de los Pesos, por separado, deben valer más que el Umbral de “2”, y claro, dos números que valen más que “2”, sumados no pueden valer menos que “2”. Entonces ¿Cómo resuelve esto el Sesgo? Corramos el código tal como en el ejemplo del Punto 6, sin modificaciones. Cuando ponemos atención en el detalle de los valores que van adquiriendo los Pesos, notamos que el Sesgo adquiere un valor positivo grande, alrededor del doble del Umbral; mientras que los valores de los otros dos Pesos, adquieren valores negativos, para un Umbral de “2”; y es como de esta forma si sumamos los dos Pesos con el Peso del Sesgo, resulta algo así como: Valores Ajustados PS = 4.5 P1 = -1.7 P2 = -1.3 E1 = 0, E2 = 0 PS 4.5 4.5 > Umbral E1 = 1, E2 = 0 PS + P1 4.5 + -1.7 = 2.8 2.8 > Umbral E1 = 0, E2 = 1 PS + P2 4.5 + -1.3 = 3.2 3.2 > Umbral E1 = 1, E2 = 1
www.fullengineeringbook.net
PS + P1 + P2 4.5 + -1.7 + -1.3 = 1.5 1.5
Después de correrlo varias veces notaras que los valores de convergencia, se encuentran con un Peso de Sesgo positivo mayor al Umbral, mientras que los Pesos de las otras dos Entradas, individualmente, deben ser negativos y de una magnitud menor a la diferencia entre el Peso del Sesgo y el Umbral, de manera que, al sumarlos individualmente al Peso del Sesgo, las sumas sigan siendo mayores al valor del Umbral; mientras que la suma de los Pesos de estas dos Entradas, ambos negativos, deberán de tener una magnitud superior a la diferencia que hay entre el Peso del Sesgo y el valor del Umbral, para que al sumarlos pueda ser inferior al valor del Umbral. Por lo tanto como veras, el Sesgo aporta más de lo que puede pesar el que le tome unas iteraciones más el aprender, por lo que en mi opinión el Sesgo es una parte imprescindible del Perceptrón; porque si bien puede hacer más lento el aprendizaje, lo compensa con creces permitiendo resolver situaciones que hacen más poderoso el Perceptrón; y así nos podemos olvidar de estar teniendo que hacer adaptaciones adicionales, conversiones en las Entradas y Salidas, o requiriendo Perceptrones más robustos que puede en tiempo de cómputo llegar a ser mayor que lo que nos “ahorramos” por el posible aprendizaje que requiere más iteraciones, que además se reflejará en el proyecto terminado en eficiencia. Tabla de Contenido
www.fullengineeringbook.net
9. Algoritmo Complementado para Ejercicios: En este Libro trabajaremos los mismos ejemplos que en el Libro pasado, pues nos servirán para realizar las comparaciones, solo que esta vez podremos resolver más casos, sin necesidad de hacer la codificación inversa. Aunque aún quedará sin poder resolver, como te comentaba, la Tabla de XOR, tal vez ya te hallas dado cuenta porque, de cualquier forma en el siguiente Libro te lo mostraré con comparaciones gráficas, para que quede más claro. A continuación te muestro las adiciones que te propongo realizar al algoritmo, que te permitirán en tiempo de ejecución, y sin tener que estar modificando el código, comparar los procesos de ingresar las diferentes Tablas de Verdad (OR, AND, NOR, NAND, XOR); además incorporaremos el código que permite activar y desactivar el Sesgo. Para enseguida desplegar el algoritmo completo. Esta basado en el del Punto 6, y lo que se agrega solo es para facilitar los ejercicio, pero en esencia sigue siendo en cuanto al Perceptrón lo mismo. Tanto la clasificación del Perceptrón, la explicación de cada una de las variables y constantes, la explicación de la puesta a punto de la configuración parámetro a parámetro, como los momentos por los que pasa un Perceptrón, son temas que ya fueron vistos en el Libro anterior, por lo que si requieres de estos temas, te sugiero que busques el Libro anterior, pues de una forma sencilla y con sentido práctico podrás cubrir los temas. Lo que se agrega es: 1. La variable para poder poner o quitar el Sesgo. 2. La carga en una sola linea de los valores de las Entradas. 3. La carga en arreglos, para cada Tabla de Verdad, con los valores de Salida requeridos. 4. Un ciclo más para poder correr ejemplo tras ejemplo. 5. La presentación de las opciones en pantalla asociadas al un número de opción. 6. La captura en ejecución del teclado de la opción seleccionada. 7. De acuerdo a la opción seleccionada se cargan los valores de Salida requeridos y se incluye o no el Sesgo. 8. La espera del usuario para presentar nuevamente las opciones. Tabla de Contenido
www.fullengineeringbook.net
9.1. Pseudocódigo Complemento: - # Sesgo - declara variable tipo int llamada: Ses - asigna a Ses el valor 0 - # Arrays: 4 Casos del Ejemplo - declara arreglo tipo int llamada: Ent de [4][2] - asigna a Ent[0][0] el valor 0 - asigna a Ent[0][1] el valor 0 - asigna a Ent[1][0] el valor 0 - asigna a Ent[1][1] el valor 1 - asigna a Ent[2][0] el valor 1 - asigna a Ent[2][1] el valor 0 - asigna a Ent[3][0] el valor 1 - asigna a Ent[3][1] el valor 1 - # Carga de Ejemplos - # Arrays: 4 Casos del Ejemplo, "Tabla OR" - asigna a SalOR[0] el valor 0 - asigna a SalOR[1] el valor 1 - asigna a SalOR[2] el valor 1 - asigna a SalOR[3] el valor 1 - # Arrays: 4 Casos del Ejemplo, "Tabla AND" - asigna a SalAND[0] el valor 0 - asigna a SalAND[1] el valor 0 - asigna a SalAND[2] el valor 0 - asigna a SalAND[3] el valor 1 - # Arrays: 4 Casos del Ejemplo, "Tabla NOR" - asigna a SalNOR[0] el valor 1 - asigna a SalNOR[1] el valor 0 - asigna a SalNOR[2] el valor 0 - asigna a SalNOR[3] el valor 0 - # Arrays: 4 Casos del Ejemplo, "Tabla NAND" - asigna a SalNAND[0] el valor 1 - asigna a SalNAND[1] el valor 1 - asigna a SalNAND[2] el valor 1 - asigna a SalNAND[3] el valor 0 - # Arrays: 4 Casos del Ejemplo, "Tabla XOR" - asigna a SalXOR[0] el valor 0
www.fullengineeringbook.net
- asigna a SalXOR[1] el valor 1 - asigna a SalXOR[2] el valor 1 - asigna a SalXOR[3] el valor 0 - # Ciclo de Ejercicios - Inicia Ciclo - # Presenta Opciones - muestra "(linea)(linea)" - muestra "- - - - - - - - - - - - - - - - - - - - " - muestra "- - Ejemplo de Perceptron Simple - - " - muestra "- - - - - - - - - - - - - - - - - - - - " - muestra "- - Menu de Opciones - - " - muestra "- - - - " - muestra "- - 1.- OR sin Sesgo - - " - muestra "- - 2.- AND sin Sesgo - - " - muestra "- - 3.- NOR sin Sesgo - - " - muestra "- - 4.- NAND sin Sesgo - - " - muestra "- - 5.- XOR sin Sesgo - - " - muestra "- - - - " - muestra "- - 6.- OR con Sesgo - - " - muestra "- - 7.- AND con Sesgo - - " - muestra "- - 8.- NOR con Sesgo - - " - muestra "- - 9.- NAND con Sesgo - - " - muestra "- - 10.- XOR con Sesgo - - " - muestra "- - - - " - muestra "- - 0.- Termina - - " - muestra "- - - - - - - - - - - - - - - - - - - - " - # Captura Opcion - muestra '(linea) Opcion del Menu : ' - captura teclado y lo asigna a Opn - # Carga del Ejercicio Elegido - Si Opn igual a '1' # OR sin Sesgo - asigna a Sal el array SalOR - asigna a Ses el valor 0 - O Si Opn igual a '2' # AND sin Sesgo - asigna a Sal el array SalAND - asigna a Ses el valor 0 - O Si Opn igual a '3' # NOR sin Sesgo www.fullengineeringbook.net - asigna a Sal el array SalNOR
- asigna a Ses el valor 0 - O Si Opn igual a '4' # NAND sin Sesgo - asigna a Sal el array SalNAND - asigna a Ses el valor 0 - O Si Opn igual a '5' # XOR sin Sesgo - asigna a Sal el array SalXOR - asigna a Ses el valor 0 - O Si Opn igual a '6' # OR sin Sesgo - asigna a Sal el array SalOR - asigna a Ses el valor 1 - O Si Opn igual a '7' # AND sin Sesgo - asigna a Sal el array SalAND - asigna a Ses el valor 1 - O Si Opn igual a '8' # NOR sin Sesgo - asigna a Sal el array SalNOR - asigna a Ses el valor 1 - O Si Opn igual a '9' # NAND sin Sesgo - asigna a Sal el array SalNAND - asigna a Ses el valor 1 - O Si Opn igual a '10' # XOR sin Sesgo - asigna a Sal el array SalXOR - asigna a Ses el valor 1 - en Otro # Salida - Sale - # Espera [Enter] para continuar - muestra '(linea) Presione [Enter] para continuar : ' - captura teclado y lo asigna a Opn Tabla de Contenido
www.fullengineeringbook.net
9.2. Código en Python Complemento: 8
# Sesgo
9
Ses = 0
14
# Arrays: 4 Casos
15
Ent = [[0 ,0] ,[0 ,1] ,[1 ,0] ,[1 ,1]]
18
# Carga de Ejemplos
19
# Arrays: 4 Casos del Ejemplo, "Tabla OR"
20
SalOR = [0, 1, 1, 1]
21
# Arrays: 4 Casos del Ejemplo, "Tabla AND"
22
SalAND = [0, 0, 0, 1]
23
# Arrays: 4 Casos del Ejemplo, "Tabla NOR"
24
SalNOR = [1, 0, 0, 0]
25
# Arrays: 4 Casos del Ejemplo, "Tabla NAND"
26
SalNAND = [1, 1, 1, 0]
27
# Arrays: 4 Casos del Ejemplo, "Tabla XOR"
28
SalXOR = [0, 1, 1, 0]
35
# Ciclo de Ejercicios
36
while True:
37
# Presenta Opciones
38
print "\n\n"
39
print "- - - - - - - - - - - - - - - - - - - - "
40
print "- - Ejemplo de Perceptron Simple - - "
41
print "- - - - - - - - - - - - - - - - - - - - "
42
print "- - Menu de Opciones - - "
43
print "- - - - "
44
print "- - 1.- OR sin Sesgo - - "
45
print "- - 2.- AND sin Sesgo - - "
46
print "- - 3.- NOR sin Sesgo - - "
47
print "- - 4.- NAND sin Sesgo - - "
48
print "- - 5.- XOR sin Sesgo - - "
49
print "- - - - "
50
print "- - 6.- OR con Sesgo - - "
51
print "- - 7.- AND con Sesgo - - "
52
print "- - 8.- NOR con Sesgo - - "
53
print "- - 9.- NAND con Sesgo - - " www.fullengineeringbook.net
54
print "- - 10.- XOR con Sesgo - - "
55
print "- - - - "
56
print "- - 0.- Termina - - "
57
print "- - - - - - - - - - - - - - - - - - - - "
59
# Captura Opcion
60
Opn = raw_input('\n Opcion del Menu : ')
62
# Carga del Ejercicio Elegido
63
if Opn == '1': # OR sin Sesgo
64
Sal = SalOR
65
Ses = 0
66
elif Opn == '2': # AND sin Sesgo
67
Sal = SalAND
68
Ses = 0
69
elif Opn == '3': # NOR sin Sesgo
70
Sal = SalNOR
71
Ses = 0
72
elif Opn == '4': # NAND sin Sesgo
73
Sal = SalNAND
74
Ses = 0
75
elif Opn == '5': # XOR sin Sesgo
76
Sal = SalXOR
77
Ses = 0
78
elif Opn == '6': # OR con Sesgo
79
Sal = SalOR
80
Ses = 1
81
elif Opn == '7': # AND con Sesgo
82
Sal = SalAND
83
Ses = 1
84
elif Opn == '8': # NOR con Sesgo
85
Sal = SalNOR
86
Ses = 1
87
elif Opn == '9': # NAND con Sesgo
88
Sal = SalNAND
89
Ses = 1
90
elif Opn == '10': # XOR con Sesgo
91
Sal = SalXOR
92
Ses = 1
93
else : # Salida
94
break
www.fullengineeringbook.net
150 # Espera [Enter] para continuar 151 Opn = raw_input('\n Presione [Enter] para continuar : ') Tabla de Contenido
www.fullengineeringbook.net
9.3. Pseudocódigo Completo: - # Constantes de los Parámetros Rígidos - declara variable tipo float llamada: Apr - declara variable tipo float llamada: Ubr - asigna a Apr el valor 1.0 - asigna a Ubr el valor 2.0 - # Variables de Control de Iteraciones - declara variable tipo int llamada: i - declara variable tipo int llamada: j - declara variable tipo int llamada: k - # Variables de Trabajo - declara variable tipo float llamada: Axn - declara variable tipo float llamada: Sum - declara variable tipo float llamada: Err - declara variable tipo int llamada: NEr - # Sesgo - declara variable tipo int llamada: Ses - asigna a Ses el valor 0 - # Array: Pesos de Memoria - declara arreglo tipo float llamado: Pes de [3] - # Arrays: 4 Casos del Ejemplo, "Tabla NAND" - declara arreglo tipo int llamada: Ent de [4][2] - asigna a Ent[0][0] el valor 0 - asigna a Ent[0][1] el valor 0 - asigna a Ent[1][0] el valor 0 - asigna a Ent[1][1] el valor 1 - asigna a Ent[2][0] el valor 1 - asigna a Ent[2][1] el valor 0 - asigna a Ent[3][0] el valor 1 - asigna a Ent[3][1] el valor 1 - declara arreglo tipo int llamada: Sal de [4] - # Carga de Ejemplos - # Arrays: 4 Casos del Ejemplo, "Tabla OR" www.fullengineeringbook.net
- asigna a SalOR[0] el valor 0 - asigna a SalOR[1] el valor 1 - asigna a SalOR[2] el valor 1 - asigna a SalOR[3] el valor 1 - # Arrays: 4 Casos del Ejemplo, "Tabla AND" - asigna a SalAND[0] el valor 0 - asigna a SalAND[1] el valor 0 - asigna a SalAND[2] el valor 0 - asigna a SalAND[3] el valor 1 - # Arrays: 4 Casos del Ejemplo, "Tabla NOR" - asigna a SalNOR[0] el valor 1 - asigna a SalNOR[1] el valor 0 - asigna a SalNOR[2] el valor 0 - asigna a SalNOR[3] el valor 0 - # Arrays: 4 Casos del Ejemplo, "Tabla NAND" - asigna a SalNAND[0] el valor 1 - asigna a SalNAND[1] el valor 1 - asigna a SalNAND[2] el valor 1 - asigna a SalNAND[3] el valor 0 - # Arrays: 4 Casos del Ejemplo, "Tabla XOR" - asigna a SalXOR[0] el valor 0 - asigna a SalXOR[1] el valor 1 - asigna a SalXOR[2] el valor 1 - asigna a SalXOR[3] el valor 0 - # Inicio Pseudo-aleatoria de los 3 Pesos - asigna a Pes[0] un valor float aleatorio entre (-1 y 1) - asigna a Pes[1] un valor float aleatorio entre (-1 y 1) - asigna a Pes[2] un valor float aleatorio entre (-1 y 1) - # Ciclo de Ejercicios - Inicia Ciclo - # Presenta Opciones - muestra "(linea)(linea)" - muestra "- - - - - - - - - - - - - - - - - - - - " - muestra "- - Ejemplo de Perceptron Simple - - " - muestra "- - - - - - - - - - - - - - - - - - - - " - muestra "- - Menu de Opciones - - " - muestra "- - - - " - muestra "- - 1.- OR sin Sesgo - - " - muestra "- - 2.- AND sin Sesgo - - " www.fullengineeringbook.net - muestra "- - 3.- NOR sin Sesgo - - "
- muestra "- - 4.- NAND sin Sesgo - - " - muestra "- - 5.- XOR sin Sesgo - - " - muestra "- - - - " - muestra "- - 6.- OR con Sesgo - - " - muestra "- - 7.- AND con Sesgo - - " - muestra "- - 8.- NOR con Sesgo - - " - muestra "- - 9.- NAND con Sesgo - - " - muestra "- - 10.- XOR con Sesgo - - " - muestra "- - - - " - muestra "- - 0.- Termina - - " - muestra "- - - - - - - - - - - - - - - - - - - - " - # Captura Opcion - muestra '(linea) Opcion del Menu : ' - captura teclado y lo asigna a Opn - # Carga del Ejercicio Elegido - Si Opn igual a '1' # OR sin Sesgo - asigna a Sal el array SalOR - asigna a Ses el valor 0 - O Si Opn igual a '2' # AND sin Sesgo - asigna a Sal el array SalAND - asigna a Ses el valor 0 - O Si Opn igual a '3' # NOR sin Sesgo - asigna a Sal el array SalNOR - asigna a Ses el valor 0 - O Si Opn igual a '4' # NAND sin Sesgo - asigna a Sal el array SalNAND - asigna a Ses el valor 0 - O Si Opn igual a '5' # XOR sin Sesgo - asigna a Sal el array SalXOR - asigna a Ses el valor 0 - O Si Opn igual a '6' # OR sin Sesgo - asigna a Sal el array SalOR - asigna a Ses el valor 1 - O Si Opn igual a '7' # AND sin Sesgo - asigna a Sal el array SalAND - asigna a Ses el valor 1 - O Si Opn igual a '8' # NOR sin Sesgo - asigna a Sal el array SalNOR - asigna a Ses el valor 1
www.fullengineeringbook.net - O Si Opn igual a '9' # NAND sin Sesgo
- asigna a Sal el array SalNAND - asigna a Ses el valor 1 - O Si Opn igual a '10' # XOR sin Sesgo - asigna a Sal el array SalXOR - asigna a Ses el valor 1 - en Otro # Salida - Sale - # Muestra en Pantalla los 3 Pesos Iniciales - muestra ("Iniciales: P0: Pes[0] P1: Pes[1] P2: Pes[2] (linea) (linea)") - # Ciclo de Intentos - # Parámetros para 1,000 Intentos - asigna a j el valor 0 - asigna a k el valor 1,000 - Inicia Ciclo # Inicia Ciclo de Intentos - incrementa j en 1 # Incrementa Contador de Intentos - # Muestra en Pantalla Intento a Calcular - muestra ("Ciclo: j - - - - - - - - -(linea)") - # Ciclo de Casos, por Intento - asigna a NEr el valor 0 # Reinicia Contador de Errores - Inicia Ciclo # Inicia Ciclo de Casos - recorre i de 0 a 3 # Recorre los 4 Casos - # Cálculo del Perceptrón para el Caso - multiplica Ent[0] por Pes[0] - multiplica Ent[1] por Pes[1] - y multiplica Ses por Pes[2] - suma resultados y los asigna a Sum - # Comparación con Umbral - Si Sum supera a Ubr: - asigna a Axn el valor 1 - En otro caso: - asigna a Axn el valor 0 - # Cálculo de Error del Caso - a Sal (salida esperada), se resta Axn (resultante) y lo asigna a Err - # Ajuste de Pesos con el Caso www.fullengineeringbook.net
- Si Err diferente de 0: # Ajusta si hay Error - incrementa NEr en 1 # Incrementa el contador de Errores - # Se realiza para cada Peso con su Entrada correspondiente - multiplica Apr por Err, y por Ent[0] - asigna el Producto más Pes[0] a Pes[0] - multiplica Apr por Err, y por Ent[1] - asigna el Producto más Pes[1] a Pes[1] - multiplica Apr por Err, y por Ses - asigna el Producto más Pes[2] a Pes[2] - # Muestra en Pantalla Entradas y Resultado - muestra ("- Caso i E1: Ent[i][0] E2: Ent[i][1] S:Sal[i] Axn:Axn") - Si Err diferente de 0 # Si hay Error - cambia color de letra a rojo; # Muestra Errores en Rojo - muestra ("Err: Err") - cambia color de letra al anterior; # Regresa el color - # Muestra a que Pesos Ajustó - muestra ("Ajusta a: P0: Pes[0] P1: Pes[1] P2: Pes[2] (linea)"); - # Termina Ciclo de Casos - # Muestra el Número de Errores del Intento - muestra ("NEr Errores - - - - - - - - -(linea) (linea)") - # Termina Anticipadamente si no hay Errores - Si contador de errores NEr es 0 - Sale del Ciclo de Intentos - Continua Ciclo Mientras j es menor que k # Termina Ciclos de Intentos - # Espera [Enter] para continuar - muestra '(linea) Presione [Enter] para continuar : ' - captura teclado y lo asigna a Opn - Termina Programa # Terminación de Programa Tabla de Contenido
www.fullengineeringbook.net
9.4. Código en Python Completo: 1
# Complemento para generar aleatorios
2
import random
3 4
# Constantes de los Parametros Rigidos
5
Apr = 1.0
6
Ubr = 2.0
7 8
# Sesgo
9
Ses = 0
10 11
# Array: Pesos de Memoria
12
Pes = [0.0, 0.0, 0.0]
13 14
# Arrays: Casos
15
Ent = [[0 ,0] ,[0 ,1] ,[1 ,0] ,[1 ,1]]
16
Sal = []
17 18
# Carga de Ejemplos
19
# Arrays: 4 Casos del Ejemplo, "Tabla OR"
20
SalOR = [0, 1, 1, 1]
21
# Arrays: 4 Casos del Ejemplo, "Tabla AND"
22
SalAND = [0, 0, 0, 1]
23
# Arrays: 4 Casos del Ejemplo, "Tabla NOR"
24
SalNOR = [1, 0, 0, 0]
25
# Arrays: 4 Casos del Ejemplo, "Tabla NAND"
26
SalNAND = [1, 1, 1, 0]
27
# Arrays: 4 Casos del Ejemplo, "Tabla XOR"
28
SalXOR = [0, 1, 1, 0]
29 30
# Inicio Pseudo-aleatoria de los 3 Pesos
31
Pes[0] = random.uniform(-1.0, 1.0)
32
Pes[1] = random.uniform(-1.0, 1.0)
33
Pes[2] = random.uniform(-1.0, 1.0)
34 35
# Ciclo de Ejercicios
36
while True:
37
# Presenta Opciones
38
print "\n\n"
www.fullengineeringbook.net
39
print "- - - - - - - - - - - - - - - - - - - - "
40
print "- - Ejemplo de Perceptron Simple - - "
41
print "- - - - - - - - - - - - - - - - - - - - "
42
print "- - Menu de Opciones - - "
43
print "- - - - "
44
print "- - 1.- OR sin Sesgo - - "
45
print "- - 2.- AND sin Sesgo - - "
46
print "- - 3.- NOR sin Sesgo - - "
47
print "- - 4.- NAND sin Sesgo - - "
48
print "- - 5.- XOR sin Sesgo - - "
49
print "- - - - "
50
print "- - 6.- OR con Sesgo - - "
51
print "- - 7.- AND con Sesgo - - "
52
print "- - 8.- NOR con Sesgo - - "
53
print "- - 9.- NAND con Sesgo - - "
54
print "- - 10.- XOR con Sesgo - - "
55
print "- - - - "
56
print "- - 0.- Termina - - "
57
print "- - - - - - - - - - - - - - - - - - - - "
58 59
# Captura Opcion
60
Opn = raw_input('\n Opcion del Menu : ')
61 62
# Carga del Ejercicio Elegido
63
if Opn == '1': # OR sin Sesgo
64
Sal = SalOR
65
Ses = 0
66
elif Opn == '2': # AND sin Sesgo
67
Sal = SalAND
68
Ses = 0
69
elif Opn == '3': # NOR sin Sesgo
70
Sal = SalNOR
71
Ses = 0
72
elif Opn == '4': # NAND sin Sesgo
73
Sal = SalNAND
74
Ses = 0
75
elif Opn == '5': # XOR sin Sesgo
76
Sal = SalXOR
77
Ses = 0
78
elif Opn == '6': # OR con Sesgo
79
Sal = SalOR
80
Ses = 1
www.fullengineeringbook.net
81
elif Opn == '7': # AND con Sesgo
82
Sal = SalAND
83
Ses = 1
84
elif Opn == '8': # NOR con Sesgo
85
Sal = SalNOR
86
Ses = 1
87
elif Opn == '9': # NAND con Sesgo
88
Sal = SalNAND
89
Ses = 1
90
elif Opn == '10': # XOR con Sesgo
91
Sal = SalXOR
92
Ses = 1
93
else : # Salida
94
break
95 96
# Muestra en Pantalla los 3 Pesos Iniciales
97
print "\033[32m Iniciales: P0:%f P1:%f P2:%f\n\n" % (Pes[0], Pes[1], Pes[2])
98 99
# Ciclo de Intentos
100 j = 0; k = 1000 # Parametros para 1,000 Intentos 101 while True: # Inicia Ciclo de Intentos 102 j += 1 # Incrementa Contador de Intentos 103 104 # Muestra en Pantalla Intento a Calcular 105 print "Ciclo:%d - - - - - - - - -" % (j) 106 107 # Ciclo de Casos, por Intento 108 NEr = 0 # Reinicia Contador de Errores 109 for i in range(4): # Inicia Ciclo de Casos 110 111 # Calculo del Perceptron para el Caso 112 Sum = Ent[i][0] * Pes[0] + Ent[i][1] * Pes[1] + Ses * Pes[2] 113 if Sum > Ubr: # Comparacion con Umbral 114 Axn = 1 # Umbral Superado 115 else: 116 Axn = 0 # Umbral No Superado 117 118 # Calculo de Error del Caso 119 Err = Sal[i] - Axn 120 121 # Ajuste de Pesos con el Caso www.fullengineeringbook.net
122 if Err != 0: # Ajusta si hay Error 123 NEr += 1 # Incrementa el contador de Errores 124 # Se realiza para cada Peso con su Entrada correspondiente 125 Pes[0] += Apr * Err * Ent[i][0] 126 Pes[1] += Apr * Err * Ent[i][1] 127 Pes[2] += Apr * Err * Ses 128 129 # Muestra en Pantalla Entradas y Resultado 130 print ("- Caso %d E1:%d E2:%d S:%d Axn:%f Sum:%f " 131 % (i, Ent[i][0], Ent[i][1], Sal[i], Axn, Sum)), 132 if Err != 0: # Si hay Error 133 print "\033[33m", # Muestra Errores en Rojo 134 print "Err: %f\033[32m" % (Err) 135 # Muestra a que Pesos Ajusto 136 print " Ajusta a: P0:%f P1:%f P2:%f" % (Pes[0], Pes[1], Pes[2]) 137 138 # Termina Ciclo de Casos 139 140 # Muestra el Numero de Errores del Intento 141 print "%d Errores - - - - - - - - -\n" % (NEr) 142 143 # Termina Anticipadamente si no hay Errores 144 if NEr == 0: 145 break 146 147 if j >= k: # Termina Ciclos de Intentos 148 break 149 150 # Espera [Enter] para continuar 151 Opn = raw_input('\n Presione [Enter] para continuar : ') 152 153 # Termina Programa Tabla de Contenido
www.fullengineeringbook.net
10. Algoritmo para Incorporar a Proyectos: Ahora que ya entendimos como funciona el algoritmo de aprendizaje del Perceptrón, te muestro una versión del Perceptrón entrenado, listo para incorporarse a nuestros proyectos para experimentar. Tabla de Contenido
www.fullengineeringbook.net
10.1. Pseudocódigo de la Función: - # Función: Perceptrón Simple - Inicia Funcion Perceptrón - recibe variable tipo int llamada: Ent_1 - recibe variable tipo int llamada: Ent_2 - # Pesos de Memoria - declara variable tipo float llamada: Pes_0 # Sesgo - declara variable tipo float llamada: Pes_1 - declara variable tipo float llamada: Pes_2 - asigna a Pes_0 valor Valor_Aprendido_0 # Sesgo - asigna a Pes_1 valor Valor_Aprendido_1 - asigna a Pes_2 valor Valor_Aprendido_2 - # Constantes de los Parámetros Rígidos - declara variable tipo float llamada: Ubr - asigna a Ubr valor 2.0 - # Variables de Trabajo - declara variable tipo float llamada: Sum - # Cálculo del Perceptrón - multiplica Ent_1 por Pes_1 - y multiplica Ent_2 por Pes_2 - suma resultados con Pes_0 - y los asigna a Sum - # Comparación con Umbral - Si Sum supera a Ubr: - regresa de función el valor 1 - En otro caso: - regresa de función el valor 0 - # Fin de Funcion: Perceptrón Simple - Termina Funcion Perceptrón Tabla de Contenido
www.fullengineeringbook.net
10.2. Código en Python de la Función: 101 # Funcion: Perceptron Simple 102 def Perceptron(Ent_1, Ent_2): 103 # Pesos de Memoria 104 Pes_0 = Valor_Aprendido_0 # Sesgo 105 Pes_1 = Valor_Aprendido_1 106 Pes_2 = Valor_Aprendido_2 107 # Constantes de los Parametros Rigidos 108 Ubr = 2.0 109 # Calculo del Perceptron 110 Sum = Pes_0 + Ent_1 * Pes_1 + Ent_2 * Pes_2 111 if Sum > Ubr: # Comparacion con Umbral 112 return 1 # Umbral Superado 113 else: 114 return 0 # Umbral No Superado Tabla de Contenido
www.fullengineeringbook.net
11. Nuevo Paradigma del Sesgo: Ahora que hemos puesto al descubierto otro aspecto del Sesgo, ya no lo veremos más como lo veíamos antes, pues le encontramos otra utilidad; no hemos cambiado sus elementos, ni características, solo descubrimos algo más para lo que es útil. Estamos trabajando con Inteligencia Artificial, y aunque solo estemos trabajando con ladrillos, por ahora, más adelante nos permitirán construir edificios, es una buena idea de que también nos hagamos conscientes de como funciona y que aplicamos de nuestra propia inteligencia, después de todo, desarrollar Inteligencia Artificial, es transferirle características de la nuestra, para que pueda aumentar su utilidad, y tal vez un día darle consciencia. Tabla de Contenido
www.fullengineeringbook.net
Retroalimentación: Tus comentarios, dudas o sugerencias serán bien recibidas. Te dejo mi correo:
[email protected] Tabla de Contenido
www.fullengineeringbook.net