Aprendizaje Automático & Patrones de Diseño de Software: una combinación de súper poderes
Por Álvaro Martínez
El contexto actual donde vivimos nos exige adaptarnos de la mejor manera, más cuando esta sociedad tiene la tendencia a tecnificarlo todo, en respuesta a ese vertiginoso desafío, viene consolidándose la inteligencia artificial (IA) como una herramienta de transformación digital que está teniendo éxito en muchos campos, por ejemplo, en medicina, finanzas, ciberseguridad y educación, entre otros. A la par, la Ingeniería de Software, a pulso, se ha ganado su lugar dentro de este gran panorama, gracias a su amplia capacidad de brindar soluciones tecnológicas casi para todo tipo de problemas, desde sencillos sistemas de información transaccionales hasta complejas aplicaciones de control en tiempo real. Ahora, ¿se imaginan el poder que podría tener la combinación de estos dos mundos tecnológicos? Este post te dará una idea de ello !
Antes que nada, permítanme conceptualizar brevemente de dónde vienen los dos súper poderes. El primero, hace parte de la IA, rama de las Ciencias de la Computación que permite crear máquinas “inteligentes” capaces de comportarse como humanos, pensar como humanos, y sobretodo y muy interesante, tomar decisiones de manera autónoma. Si analizamos las palabras que componen la IA, nos damos cuenta que artificial, hace referencia a todo lo creado por un humano, e inteligencia, a la capacidad de pensar por sí mismo. De igual manera, cuando hablamos del proceso llevado a cabo en proyectos de IA la literatura nos muestra un camino que se pasa por las etapas de planeación, razonamiento, análisis de datos, predicción y actuación en consecuencia con los resultados obtenidos e involucra en su desarrollo herramientas matemáticas como la estadística y probabilidad. Una parte de la IA es el Aprendizaje Automático o en inglés, Machine Learning (ML), que le permite a un sistema aprender por sí mismo a través de la experiencia (Dhankar & Walia, 2020). De acuerdo con las necesidades específicas, existen varios ciclos de vida del ML, a continuación, se describe uno de ellos: se inicia definiendo un problema que guiará el tipo de modelo de ML a construir, a partir de él, se desarrolla un proceso iterativo que comienza con la gestión de datos que incluye su recolección de diferentes fuentes y su preparación, como resultado se obtiene un conjunto de datos (dataset) que muchos expertos recomiendan sea de gran volumen de registros para obtener mejores resultados; la información ya preparada se convierte en materia prima para la creación del modelo de ML que responda al problema planteado inicialmente, en este punto se divide el dataset, comúnmente, en dos subconjuntos: el de entrenamiento y el de prueba, el primero se usa para “educar” a la máquina haciendo uso de un algoritmo de ML y el segundo para probar el modelo con datos desconocidos, al final la intención es que el sistema logre obtener los mejores resultados con datos que no fueron usados en el entrenamiento, de esta manera se evita el sobreajuste o encontrar soluciones demasiado específicas o exactas a los datos de entrenamiento; posteriormente, y con el objeto de contar con los mejores resultados, al modelo entrenado y probado, se le van configurando paulatinamente sus hiperparámetros hasta encontrar la mejor solución, al cabo de ello, se despliega el modelo de ML, cuyo objetivo es poder brindar a los usuarios finales los servicios del modelo para sus propósitos en particular; finalmente, se monitorea la forma en que el modelo trabaja y si es necesario se ajusta.
El segundo súper poder se encuentra en la Ingeniería de Software, permítanme contarles algo de ella, según el ACM CCECC, esta disciplina consiste en la fabricación de manera sistemática, controlada y eficiente de programas de computador confiables y de alta calidad utilizando métodos formales en la especificación, evaluación, análisis y diseño, implementación, prueba y mantenimiento. En todo el proceso descrito anteriormente, una de las etapas cruciales en la fabricación de software es el diseño ya que de él depende, en gran medida, la capacidad de satisfacer los requerimientos del cliente en la solución propuesta y su evolución en el tiempo a bajo costo, en este sentido, aplicar las mejores prácticas garantiza un alto porcentaje de éxito en los proyectos de este tipo, una de ellas es la utilización de los patrones de diseño de software, que se popularizaron y se convirtieron en referente con “la banda de los cuatro” (Gang of Four) en su libro Design Patterns (Gamma, Helm, Johnson, & Vlissides, 1994), los autores de este texto luego de ahondar en las soluciones software que se estaban produciendo en el mercado, se percataron que muchos problemas se podían resolver de maneras comunes y que en el pasado existían ya personas que habían lidiado con esos retos, aprovechando tal situación, propusieron 23 formas reutilizables de resolver problemas típicos que las llamaron Patrones de Diseño de Software cuyos beneficios, entre muchos más, son: ahorrar tiempo de desarrollo, porque no se empieza de cero; asegurar la validez del código, porque las instrucciones que se escriben ya han sido probadas por otros; y trabajar con un lenguaje común, hecho que ayuda a los desarrolladores a entender las soluciones y poderlas escalar y mantener. Los patrones pueden clasificarse en varios grupos, dependiendo del tipo de problema que aborden. Cuando se quiera crear objetos encapsulando el proceso, ayudarán los patrones creacionales; por el contrario, si el deseo es especificar de manera clara cómo las clases se están relacionando, usar patrones estructurales está bien; ahora, si lo que inquieta es gestionar algoritmos, relaciones y responsabilidades de objetos, se preferirán los patrones de comportamiento.
Ya con una idea inicial de Aprendizaje Automático y Patrones de Diseño de Software, paso a contar cómo su utilización, de manera integrada en un proyecto de IA, puede resultar interesante.
¡Los súper poderes en acción!
Para ilustrar cómo el Aprendizaje Automático y los Patrones de Diseño de Software pueden trabajar en equipo en la solución de un problema, acudiré al trabajo de Nicolás Cabrales (2020), cuyo objetivo fue el desarrollo de un componente software que permita reconocer un grupo de órdenes dadas por una persona utilizando gestos dados con la mano y el brazo en streaming de video. Los servicios del aplicativo fueron tomar y liberar el control de mando, reconocer persona al mando, reconocer y procesar orden dada por una persona, liberar automáticamente el control de mando, registrar usuarios y bloquear usuarios.
En el proyecto mencionado, específicamente en el campo de la IA se realizó una revisión bibliográfica para determinar las mejores técnicas en cada etapa del reconocimiento de gestos e incluirlas en el pipeline propuesto, en la Figura 1 puede verse cómo en la etapa de análisis de información del modelo de cuatro etapas para el procesamiento de información humana propuesto por Cao et. al. se plantea un pipeline combinando métodos que se describen a continuación. La adquisición de información tomó como fuente las imágenes de streaming de video; para la detección de la persona al mando se utilizó el algoritmo de detección de objetos en tiempo real YOLO V3; en la identificación del usuario se trabajó con FaceNet; para la estimación de pose fue usado el trabajo de detección de “Key points” de Sun et. al.; y la clasificación de gestos se hizo con un modelo de Embeddings que aprenda a comparar la locación de las “land marks” producidas por el estimador de pose.
Una vez listo el modelo de IA para reconocer gestos, el paso siguiente fue implementarlo en un componente software, para ello se tomó la decisión de hacerlo, no de la forma tradicional orientado a funcionalidades como muchos trabajos de ML lo hacen, sino más bien fabricar tres subcomponentes aplicando Patrones de Diseño de Software de acuerdo con las características del pipeline propuesto. El primero se destinó para procesar la identificación de órdenes, el segundo para la vigilancia de estado del control del mando, y el tercero para el manejo de notificación de eventos cuando la acción de respuesta se activa. Las tres piezas de software mencionadas anteriormente, se corresponden con las necesidades de servicios, estado y eventos de la aplicación que se construyó. En párrafos siguientes se pasa a explicar los patrones de diseño aplicados en cada una de ellas.
Servicios
La intención de esta necesidad en un subcomponente fue la de encapsular las implementaciones e interacción de los modelos de redes neuronales utilizadas para ejecutar las tareas de detección de personas, identificación de usuarios, estimación de pose y clasificación de orden dada. Debido a las características ya mencionadas, el patrón de diseño que mejor responde es fachada (Facade), con él se consigue abstraer, a las personas que usen el componente final, la implementación total de las tareas propias del análisis de información en la tarea de identificación de órdenes. Específicamente se utilizaron las fachadas opacas porque se desea ocultar completamente la implementación de las acciones y la forma en que se orquestan para lograr la identificación de la orden. En otras palabras, la fachada en este subcomponente de servicios permitió incluir, de manera sencilla y clara, métodos con llamadas genéricas a las tareas propias del análisis de información en la identificación de órdenes sin importar qué tipo de algoritmos de ML se usen para conseguir el objetivo. Por ejemplo, en la tarea de detección de objetos se utilizó YOLO V3, pero cuando este algoritmo evolucione a versiones superiores, gracias a que su implementación se encuentra detrás de la fachada, simplemente se actualizará el código sin afectar el resto de codificación escrita, en la Figura 2 puede verse un ejemplo del patrón aplicado para la tarea de detección de personas.
Figura 1. Pipeline propuesto para el reconocimiento de gestos
Fuente: (Cabrales, 2020)
Estado
De acuerdo con los requerimientos el componente necesita mantener un estado interno de que dependerán las tareas que se ejecute y los eventos que se generen, por ejemplo, si se está en estado Idle, el software permanentemente buscará usuarios e intentará establecer si alguno quiere tomar el mando, por el contrario, si se está en estado Active, se buscará al usuario al mando y se establecerá el comando que trata de comunicar; este comportamiento claramente obedece a los patrones creacional Singleton y de comportamiento State. El primero fue usado para mantener una instancia única del sistema, y el segundo, para generar, mantener y cambiar el estado interno del componente haciendo uso de tres elementos a saber: objeto contenedor, encargado de representar una máquina en ejecución y consultar el estado actual del sistema, una interfaz, que enumera las acciones para cambiar de estado, y un conjunto de implementaciones, que representan concretamente los estados posibles e implementan las acciones. La Figura 3 muestra la máquina de estado para State y la 4 el diagrama de clases que combina State y Singleton.
Figura 2. Patrón Facade para el servicio de detección de personas
Fuente: adaptada de (Cabrales, 2020)
Eventos
El componente de reconocimiento de órdenes gestuales al identificar y reconocer personas o usuarios y órdenes, cambia de estado de acuerdo con las necesidades, para lograr este objetivo de manera automática, se implementó un gestor de eventos mediante el patrón Observer, cuya implementación permitió notificar, a modo de evento, a todos los suscriptores cuando un usuario al mando ha realizado una acción conocida. La utilidad de Observer radica en que quienes utilicen el componente únicamente tendrán que implementar la interfaz IObserver y suscribirse para ser notificados automáticamente cada vez que el sistema reconoce que un usuario está dando una orden. La Figura 5 muestra el modelo de clases diseñado para la implementación del manejador de eventos con el patrón aplicado.
Figura 3. Máquina de estado para el sistema
Fuente: (Cabrales, 2020)
Figura 4. Combinación de patrones State y Singleton para el sistema
Fuente: adaptada de (Cabrales, 2020)
Figura 5. Patrón Observer para el sistema
Fuente: adaptada de (Cabrales, 2020)
Conclusión
La IA se ha convertido en una herramienta clave dentro de la transformación digital en este mundo global donde la capacidad de saber qué hacer con la información se ha convertido en una obligación y ha permitido a diferentes organizaciones de diferentes sectores tener ventaja frente a sus similares, ahora bien, cuando esta tecnología se implementa en sistemas software utilizando las mejores prácticas existentes en la fábrica de aplicaciones se gana mayor potencial, en definitiva, combinar los poderes de la IA y Patrones de Diseño de Software seguirá siendo un objetivo imprescindible a alcanzar por quienes trabajan en el mundo de las Tecnologías de la Información, aunque se vislumbre un posible reemplazo de los profesionales de la Ingeniería de Software por sistemas de IA (Alkashri, Siyam, & Alqaryouti, 2020), no obstante, nuestra creatividad no ha sido superada por máquinas “inteligentes” y podemos aprovechar esa varita mágica.
Referencias
Alkashri, Z., Siyam, N., & Alqaryouti, O. (2020). A detailed survey of Artificial Intelligence and Spftware Engineering: Emergent Issues. 2020 Fourth International Conference on Inventive Systems and Control (ICISC), 666–672. https://doi.org/10.1109/ICISC47916.2020.9171118
Cabrales, N. (2020). Identificación de órdenes dadas con gestos utilizando Deep Learning sobre streaming de video. Universidad Internacional de la Rioja.
Dhankar, M., & Walia, N. (2020). An Introduction to Artificial Intelligence. In M. Kumar, R. Choudhary, & S. K. P. Pandey (Eds.), Emerging Trends in Big Data, IoT and Cyber Security (1st ed., pp. 105–108). Kishangarh, Vasant Kunj, New Delhi: Ecellent Publishing House. Retrieved from https://msi-ggsip.org/wp-content/uploads/conference2020.pdf#page=118
Gamma, E., Helm, R., Johnson, R., & Vlissides, J. (1994). Design Patterns – Elements of Reusable Object-Orientes Software. (K. Zhang, Ed.). Addison-Wesley Professional.