Si estás en el mundillo del desarrollo de software, seguro que el término DevOps te resulta familiar… y quizás hayas oído hablar de otros más recientes como DataOps, DevSecOps y demás.

Más allá de la moda de añadir -ops a términos ya conocidos, estos determinan y agrupan una serie de buenas prácticas que pueden ayudar a nuestra empresa a mejorar sus flujos y procesos, aprendiendo de aquellos que más saben de cada rama de desarrollo.

¿Qué es MLOps?

Se podrían dar muchas definiciones y seguramente ni siquiera los expertos se pongan de acuerdo exactamente en cuanto a qué comprende el término MLOps, pero en este artículo nos vamos a referir al él como un conjunto de mejores prácticas implantadas a la hora de desarrollar modelos de machine learning con el objetivo de ponerlos posteriormente en producción.

Esto último es importante, ya que si no, nos estaremos refiriendo a proyectos de investigación donde algunas de las prácticas que vamos a cubrir, o bien, no aplican, o no son tan relevantes como en un modelo en producción.

En términos generales, se puede hablar de mejores prácticas en cuanto a:

  • Gestión de los datos.
  • Desarrollo de modelos.
  • Robustez del despliegue.
  • Monitorización y seguimiento del modelo en producción.

MLOps aplicado

Para cada equipo de desarrolladores, los puntos anteriores pueden tener distintos significados y su importancia variará en función del proyecto que tengamos entre manos.

Sin embargo, podemos encontrar un consenso sobre la forma en la que aplicamos acciones encaminadas a observar dichos principios en un paper escrito por algunos ingenieros de Google que se han topado ya con estos problemas, de título “The ML Test Score: A Rubric for ML Production Readiness and Technical Debt Reduction”.

En este paper, Google propone un test de robustez del ciclo de vida de un proyecto de Machine Learning y otorga una nota en base a si estamos cumpliendo ciertas prácticas para cada uno de los 4 aspectos que considera: datos y características, desarrollo de modelos, infraestructura y monitorización.

Se consideran 7 tests por cada uno de los 4 bloques. Veamos cuáles son:

Datos y características:

  • Se registran las propiedades estadísticas de las variables explicativas.
  • Todas las variables aportan poder explicativo.
  • Se controla el coste de las variables.
  • Las variables cumplen las políticas previamente definidas.
  • Existen controles de privacidad.
  • Se pueden incorporar variables con rapidez.
  • Todo el código de variables se testea.

Desarrollo de modelos:

  • Las especificaciones del modelo se revisan y guardan en un repositorio.
  • Las métricas online y offline correlan.
  • Todos los hiperparámetros han sido ajustados.
  • El impacto de la obsolescencia del modelo se ha medido.
  • No hay un modelo más sencillo.
  • El modelo se comporta bien en secciones de datos relevantes.
  • El modelo es inclusivo.

Infraestructura:

  • El entrenamiento es replicable.
  • El código del modelo se testea.
  • Hay tests de integración.
  • Comprobamos la calidad del modelo antes de subirlo a producción.
  • Se puede debugear el modelo.
  • Los nuevos modelos se despliegan por etapas.
  • Es posible restaurar versiones de modelos en producción

Monitorización:

  • Existe un proceso de notificación de cambios en los datos de entrada.
  • Los datos de inferencia y los de entrenamiento tienen las mismas propiedades.
  • Las variables sintéticas de inferencia y las de entrenamiento se calculan igual.
  • Los modelos tienen vigencia.
  • Los modelos son estables numéricamente.
  • El tiempo de ejecución no ha aumentado
  • La calidad de la predicción no se ha degradado.

En el paper original hay indicaciones más detalladas de lo que implica cada test y sugerencias de cómo implementarlos.

Se define un score de la siguiente forma:

  • Medio punto por cada test implementado de forma manual
  • Un punto por cada test que se efectúa automáticamente

Finalmente, se toman por separado los puntos de cada bloque y se computa el mínimo de los 4, siendo éste el score final.

Interpretación del Score:

0 - Es más un proyecto de investigación que un desarrollo para producción.

(0,1] - Mínimamente testeado, pero con serios fallos de robustez.

(1,2] - Nivel básico de producción, pero es conveniente invertir más en él.

(2,3] - Cobertura de test razonable, pero puede que haya automatizaciones posibles.

(3,5] - Robustez suficiente para elementos críticos en producción.

>5 - Excepcionalmente bien testado y monitorizado.

El paper de Google nos ofrece unas pautas para implementar la filosofía MLOps, pero no nos dice exactamente cómo hacerlo. Para poder ejecutar todos esos tests, nos harían falta distintas herramientas o desarrollos a medida.

En este artículo nos centraremos en aquellas prácticas que son específicas de desarrollo de machine learning (en contraposición a técnicas genéricas de desarrollo como, por ejemplo, tests unitarios).

Algunos de los retos más comunes, cuando nos encontramos con este tipo de desarrollos, son el versionado y trazabilidad de modelos y resultados, que va un paso más allá del simple versionado de código.

MLflow

Es una herramienta desarrollada por los creadores de Databricks que proporciona funcionalidades nuevas pero críticas a la hora de implementar un desarrollo de ML sólido.

Consta de 3 módulos independientes, que se pueden usar standalone o en conjunción unos con otros.

Otra característica reseñable de MLflow es que funciona en cualquier cloud o en local.

Vamos a ver las funcionalidades más relevantes a través de un sencillo ejemplo.

MLflow tracking

Nos permite hacer un seguimiento de todas las ejecuciones de entrenamiento de nuestros modelos, de forma que siempre podremos recuperar para cada entrenamiento nuestro código, parámetros, métricas, modelos y cualquier otro tipo de artefacto que queramos loguear. Veamos un ejemplo:

import pandas as pd 
import numpy as np 
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
from sklearn.linear_model import ElasticNet
from sklearn.datasets import load_boston

import mlflow
import mlflow.sklearn

data = load_boston()
df = pd.DataFrame(data.data, columns=data.feature_names)

xtest,xtrain,ytest,ytrain = train_test_split(df.drop(['CRIM'],axis=1), df['CRIM'])

en = ElasticNet()

def eval_metrics(actual, pred):
    rmse = np.sqrt(mean_squared_error(actual, pred))
    mae = mean_absolute_error(actual, pred)
    r2 = r2_score(actual, pred)
    return rmse, mae, r2

def train(alpha,l1_ratio):
    with mlflow.start_run():
            lr = ElasticNet(alpha=alpha, l1_ratio=l1_ratio)
            lr.fit(xtrain, ytrain)

            predicted_qualities = lr.predict(xtest)

            (rmse, mae, r2) = eval_metrics(ytest, predicted_qualities)

            print("Elasticnet model (alpha=%f, l1_ratio=%f):" % (alpha, l1_ratio))
            print("  RMSE: %s" % rmse)
            print("  MAE: %s" % mae)
            print("  R2: %s" % r2)

            mlflow.log_param("alpha", alpha)
            mlflow.log_param("l1_ratio", l1_ratio)
            mlflow.log_metric("rmse", rmse)
            mlflow.log_metric("r2", r2)
            mlflow.log_metric("mae", mae)

            mlflow.sklearn.log_model(lr, "model")

alpha = np.arange(0,5,0.1)
l1_ratio = 0.5

for a in alpha:
    train(a,l1_ratio)

En este código hemos cargado el dataset Boston desde scikit-learn y hemos ajustado un modelo ElasticNet con dos parámetros: alpha y l1_ratio, que se corresponden con el learning rate y el l1_ratio con el coeficiente de regulación de Lasso.

Por simplicidad, hemos dejado el segundo parámetro fijo y nos hemos centrado en ir cambiando el alpha, para ver el efecto que tiene en la precisión de nuestro algoritmo.

Para poder seguir nuestros resultados con facilidad, MLflow pone a nuestra disposición una interfaz gráfica a la que podemos acceder escribiendo mlflow ui en el directorio de trabajo donde tenemos nuestro archivo .py.

Podemos acceder a él en la dirección web que nos aparece http://kubernetes.docker.internal:5000

Una vez aquí, podemos seleccionar nuestros entrenamientos y hacer click en el botón “compare” para poder verlos contrapuestos.

De esta forma accedemos a los resultados de nuestros entrenamientos y podemos ver de forma gráfica cómo se comporta nuestro modelo evaluando las diferentes métricas con los distintos valores de nuestros hiperparámetros:

En nuestro ejemplo podemos ver claramente cómo el error absoluto medio decrece a medida que aumentamos el valor de alpha.

MLflow Projects

Este módulo es, en esencia, una convención respecto al formato de código y entornos que usamos para desarrollar nuestros modelos de forma que sea exportable y accesible por otros científicos de datos.

Podemos trabajar con entornos exportables en conda, Docker o en nuestro propio entorno de sistema. En este ejemplo usaremos un entorno de conda.

Para beneficiarnos de todas las ventajas de projects, es necesario crear un MLproject file donde podemos especificar los entornos necesarios para ejecutar nuestro programa, además de especificar nuestros puntos de entrada y los parámetros de ejecución.

Para este sencillo caso creamos el siguiente archivo, que se ha de llamar forzosamente MLproject (sin extensión).

name: ejemplo_mlflow
 
conda_env: environment.yaml
 
entry_points:
  main:
    parameters:
      alpha: {type: float, default: 0.5}
      l1_ratio: {type: float, default: 0.1}
    command: "python train.py {alpha} {l1_ratio}"

Hay dos cuestiones importantes que tenemos que considerar a la hora de crear este archivo:

  • Habremos de exportar el entorno de conda en el que estamos ejecutando nuestro código. Esto lo hacemos con la instrucción sencilla conda env export > environment.yaml
  • Hemos de especificar uno por uno nuestros entry points con los parámetros que necesitamos y el comando que ejecuta nuestro programa.

Una vez hemos exportado el entorno y creado nuestro archivo MLproject, podemos ejecutar el programa con la siguiente instrucción:

mlflow run [URI]

La URI puede ser simplemente un “.” si el archivo MLprojects se encuentra en nuestro directorio local, o bien un directorio “examples/run” o podemos ejecutarlo directamente desde un repositorio remoto, añadiendo la URI del mismo.

El efecto en cualquiera de estos casos es el mismo, se genera un entorno nuevo de conda en nuestra máquina y se ejecuta el código según el comando que hemos especificado en nuestro entry point.

De esta forma logramos que cualquier desarrollador sea capaz de ejecutar nuestro código en su máquina, aislando las dependencias en el correspondiente entorno de conda.

MLflow Models

Este otro módulo de MLflow nos permite empaquetar modelos de forma estandarizada, lo que facilita su posterior puesta en producción.

Podemos beneficiarnos de diversas formas de empaquetar modelos para que puedan ser interpretados por los diferentes frameworks de producción. Algunos de los sabores o “flavors” nativos son python_function, pytorch, keras, tensorflow y otros.

MLflow models nos permite subir estos modelos a Azure ML, Amazon Sagemaker o servirlos mediante una API REST. Las funcionalidades de este módulo son muy amplias y merecen un artículo independiente, así que las cubriremos en siguientes entregas de esta serie.

Conclusión

En este artículo hemos examinado brevemente algunos de los retos únicos que supone poner nuestros modelos de Machine Learning en producción.

Para ello, nos hemos apoyado en las recomendaciones de Google y además hemos explorado una de las herramientas open source más importantes que nos pueden ayudar a atajar los problemas que nos surgen a la hora de servir nuestros modelos “live”.

Dado que este campo es relativamente nuevo, es interesante seguir la aparición de aplicaciones que tratan de solventar los problemas con los que la industria se va encontrando, y MLflow es una de las más interesantes.

Puede ahorrarnos muchos quebraderos de cabeza a la hora de estandarizar nuestros procesos de desarrollo y despliegue y es sin duda de gran ayuda para los profesionales de la IA.

Cuéntanos qué te parece.

Los comentarios serán moderados. Serán visibles si aportan un argumento constructivo. Si no estás de acuerdo con algún punto, por favor, muestra tus opiniones de manera educada.