Home

miércoles, 24 de agosto de 2011

El Aprendizaje de los Algoritmos

En el área de ingeniería del software, el término mantenimiento siempre ha tenido connotaciones negativas y subjetivas, debido principalmente a que el producto con el cual se trabaja no existe como medio "tangible" y que a diferencia de otras áreas, el desarrollo de software no está tan avanzado como para evitar la existencia de "defectos".

En las últimas semanas, dado que he retomado algunas actividades de desarrollo críticas, orientadas al mantenimiento y gestión de productos de software me he topado con varias situaciones en donde:

  1. El código implementado necesita un "retoque" orientado a adaptarlo a los requerimientos originales.
  2. El producto después de implantado en producción requiere "ajustes" necesarios para su correcto funcionamiento en producción.
Ahora, naturalmente tendemos a clasificar cualquier trabajo de mantenimiento como "defecto" o "mejora", pero hay una especie de trabajo de mantenimiento en donde no tenemos esa clasificación: El aprendizaje de los algoritmos a partir de su ejecución.

Es fácil hablar de mantenimiento en otras áreas, por ejemplo, la mecánica automotriz, en donde tenemos:
  1. Mantenimiento Correctivo, en donde clasificamos la reparación de desperfectos o instalación de accesorios.
  2. Mantenimiento Preventivo, en donde clasificamos el cambio de aceite, las actividades de limpieza, el lavado del carro, etc.
Ahora, cuando hablo de aprendizaje de los algoritmos, no hablo de inteligencia artificial ni de que los algoritmos aprendan de sus ejecuciones con el formalismo que esto conlleva, sino que hablo de la necesidad de los algoritmos de evolucionar, de cambiar a partir de necesidades en las siguientes áreas:
  • Diseño de la solución
  • Requerimientos
  • Comportamiento del algoritmo con datos de producción.
En otras palabras, hablo de aprendizaje de los algoritmos como la tarea de mantenimiento enfocada en revisar nuevamente el funcionamiento de los algoritmos internos del producto en ambientes de producción, en donde si bien las reglas de negocio no cambian, un producto de uso masivo es tratado "sin clemencia" por usuarios ávidos de información.

Para no ahondar en la parte teórica, les explico mi caso:

Supongan una tienda de ropa en donde los empleados reciben bonificaciones por varias características de la venta como tal, por ejemplo:
  • La fecha de la venta
  • La talla de la ropa
  • El tipo de ropa
  • Las ventas totales del día de la tienda
  • Las ventas totales del empleado
  • Del orden de ventas realizadas
Ahora, pensemos en un sistema que calcule las comisiones de acuerdo a esas variables, validando reglas de negocio por cada característica y que propone un paquete de bonificaciones para un empleado en un período en particular.



Dado que para un conjunto de ventas cualquiera las condiciones para cálculo de comisiones no pueden ser probadas en su totalidad, es 100% probable que el sistema salga a producción sin haber probado todas las posibles combinaciones de ventas, y peor aún, con una expectativa muy alta por parte de los usuarios de que los resultados van a estar correctos y conformes con la realidad.

Esto es crónica de una muerte anunciada.

La realidad es que es muy complejo y costoso validar el comportamiento del sistema en todos los escenarios, por lo que el sistema requerirá trabajo de mantenimiento constante.

En este escenario, el equipo de proyecto pueden tomar dos posiciones para afrontar la situación:
  • Que el sistema sale a producción defectuoso, lleno de errores y no alineado con la necesidad de negocio
  • Que el sistema sale a producción sin saber todo sobre el negocio y que es necesario ver cómo se comporta para ir enseñando al algoritmo a aprender sobre el problema que está tratando de resolver.
Mi punto es que si bien las dos visiones hablan de un producto incompleto, ambas plantean esquemas de resolución diametralmente distintas, y obviamente mi pensamiento es que es menos traumático un pase a producción si estamos consientes de que vamos a tener que seguir modificando el código. Una persona que entra nueva en un trabajo al principio se enfoca en "aprender" más que en "producir", hasta el momento en el que alcanza una "madurez" laboral. Yo planteo que lo mismo ocurre con este tipo de sistemas.

Si ahora pensamos detenidamente en qué cambian las prácticas de desarrollo y mantenimiento de este tipo de soluciones hay cambios que realmente impactan:
A nivel de levantamiento de requerimientos y diseño
  1. Se deben definir atributos de fiabilidad que permitan evaluar el desempeño de la solución bajo un espectro diferente a "Malo o Bueno". Los ejemplos usuales son % de exactitud o afines. Una solución que no tiene atributos de fiabilidad, está condenada al fracaso.
  2. Los atributos de calidad como desempeño, escalabilidad y facilidad de mantenimiento no pueden dejarse a un lado. Este tipo de sistemas usualmente requieren un tiempo importante
A nivel del desarrollo de los sistemas
  1. Se deben incluir secciones de código cuyo único fin sea recopilar métricas de cómo se comporta el algoritmo (Decisiones tomadas, tiempo de ejecución, validaciones y resultados). Este tipo de métricas permiten entender cómo realmente el algoritmo se está comportando.
  2. Los ciclos de pruebas no sólo deben hacer pruebas funcionales, sino que las pruebas de desempeño, tiempo de respuesta y escalabilidad son imprescindibles. Aqui el cambio fundamental es el atender a los diferentes atributos de calidad definidos para la solución. No es lo mismo calcular las comisiones de una tienda de 5 empleados que de una cadena de tiendas a nivel nacional con miles de empleados.
  3. Siempre debe desarrollarse un camino alternativos de soluciones menos eficientes pero más seguros, y sobre todo, más simples. En el caso de las comisiones, un algoritmo de comisión fija (por ejemplo 5% de comisión) siempre es bienvenido. Teniendo este tipo de soluciones simples, puedes asegurar que la experiencia de usuario no se verá tan afectada que si al no tener una solución se lanza una pantalla de excepción.
Al momento de realizar las pruebas
  1. Se deben estructurar las pruebas desde el conjunto de validaciones más real para luego llegar al conjunto de escenarios más ideales. Esto implica que si el escenario real es el escenario más complejo, ese el primero que se debe probar. Mi experiencia es que los equipos de prueba se centran en los escenarios ideales, en donde el flujo de actividades es tan utópico que nunca ocurre en la vida real.
  2. La ejecución de las pruebas debe automatizarse y se acumulativa, de tal manera que con cada cambio al sistema se pueda volver a ejecutar todo el ciclo de pruebas lo más costo/efectivo posible.
Al nivel del pase a producción
  1. El equipo de desarrollo debe estar revisando las métricas de desempeño como parte de sus actividades, validando el comportamiento de la aplicación y proponiendo cambios en el algortimo para que pueda "aprender" de las soluciones.
  2. Es costumbre en estos escenario plantear un hotfix a cotro plazo (no más de dos semanas) en donde se resuelvan los defectos y mejoras principales. Luego se acostumbra un ciclo de releases mensuales hasta que se llegue a la madurez del algoritmo.
Siempre y cuando lo amerite, un algoritmo que aprende es una excelente oportunidad para plantear soluciones creativas a problemas realmente complejos de gestión y procesamiento de la información.

La duda que queda, es si en los proyectos donde nos encontramos se ha hecho el análisis de cuáles son las funcionalidades, algoritmos y requerimientos que nos llevan a generar "algoritmos que aprenden" está claro, o simplemente se convierten en una lista más de defectos que convierten una solución en una "mala aplicación".

Gelvis Sequera
Twitter: @gelvisdaniel

1 comentario:

María Fernanda Fernandez Ch. dijo...

Excelente planteamiento, y sencillo de entender para desarrolladores, arquitectos, etc., pero también para roles menos técnicos.