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:

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:

Desarrollo de modelos:

Infraestructura:

Monitorización:

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:

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:

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.

Enviar.

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.