ScikitLearn
Tutorial ScikitLearn: Exportar e importar Pipelines
Scikit-Learn y la serialización y deserialización de Pipelines entrenados con joblib y pickle para optimizar su reutilización. Aprende sobre transformaciones y caché.
Aprende ScikitLearn GRATIS y certifícateGuardado y carga de Pipelines entrenados
El guardado y la carga de Pipelines entrenados son procesos esenciales para reutilizar modelos en diferentes entornos o momentos sin necesidad de reentrenarlos. Scikit-Learn proporciona herramientas eficientes para persistir modelos y Pipelines mediante serialización. A continuación, se detallan los pasos y consideraciones para lograrlo.
Para preservar la integridad del Pipeline, es fundamental guardar tanto las transformaciones de preprocesamiento como el modelo final. Esto garantiza que, al cargar el Pipeline, se puedan realizar predicciones sobre nuevos datos sin necesidad de repetir el proceso de entrenamiento.
Uso del parámetro memory
en Pipelines
El parámetro memory
permite almacenar en caché las transformaciones intermedias del Pipeline, optimizando el tiempo de ejecución en sucesivas llamadas. Al especificar una ruta donde almacenar la caché, Scikit-Learn reutiliza los resultados de las transformaciones que no hayan cambiado.
from sklearn.pipeline import Pipeline
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from joblib import Memory
# Configuración del almacenamiento en caché
memoria_cache = Memory(location='ruta_a_cache_dir', verbose=0)
# Creación del Pipeline con el parámetro "memory"
pipeline = Pipeline([
('escalador', StandardScaler()),
('clasificador', LogisticRegression())
], memory=memoria_cache)
# Entrenamiento del Pipeline
pipeline.fit(X_entrenamiento, y_entrenamiento)
En este ejemplo, se ha configurado el almacenamiento en caché mediante el objeto Memory
de joblib
, especificando una ruta para la caché. Al establecer el parámetro memory
, se mejora la eficiencia del Pipeline, especialmente en procesos de validación cruzada o ajuste de hiperparámetros.
Guardado de un Pipeline entrenado
Una vez entrenado el Pipeline, se puede utilizar la función dump
de joblib
para serializar y guardar el objeto en disco:
import joblib
# Guardado del Pipeline entrenado
joblib.dump(pipeline, 'modelo_entrenado.pkl')
Es importante destacar que al guardar el Pipeline, también se almacena la configuración del parámetro memory
, lo que permite mantener la optimización al cargarlo posteriormente.
Carga de un Pipeline entrenado
Para cargar el Pipeline previamente guardado y utilizarlo para realizar predicciones, se emplea la función load
de joblib
:
# Carga del Pipeline entrenado
pipeline_cargado = joblib.load('modelo_entrenado.pkl')
# Realizar predicciones con el Pipeline cargado
predicciones = pipeline_cargado.predict(X_nuevos)
Si el Pipeline fue configurado con una ruta de caché en el parámetro memory
, es recomendable verificar que dicha ruta exista en el entorno actual. En caso contrario, se puede actualizar la ruta de caché después de cargar el Pipeline:
# Actualizar la ruta de caché si es necesario
pipeline_cargado.memory = Memory(location='nueva_ruta_cache', verbose=0)
Uso de Pickle para serialización
Alternativamente, se puede utilizar el módulo pickle
de Python para guardar y cargar objetos:
import pickle
# Guardado del Pipeline entrenado con pickle
with open('modelo_entrenado.pkl', 'wb') as archivo:
pickle.dump(pipeline, archivo)
# Carga del Pipeline entrenado con pickle
with open('modelo_entrenado.pkl', 'rb') as archivo:
pipeline_cargado = pickle.load(archivo)
Aunque pickle
es una opción válida, joblib
está optimizado para objetos voluminosos y suele ser más eficiente en términos de velocidad y tamaño de los archivos resultantes.
Consideraciones adicionales
- Compatibilidad de versiones: Es crucial asegurarse de que la versión de Scikit-Learn utilizada para cargar el Pipeline sea la misma o compatible con la versión utilizada para guardarlo. Diferencias de versión pueden causar errores o comportamientos inesperados.
- Dependencias externas: Si el Pipeline incorpora funciones personalizadas o transformadores definidos por el usuario, se debe garantizar que dichas definiciones estén disponibles en el entorno donde se cargue el Pipeline.
- Seguridad: Al cargar archivos serializados, especialmente si provienen de fuentes no confiables, se debe tener precaución debido a posibles riesgos de seguridad asociados con la ejecución de código malicioso.
Uso de joblib
y pickle
para serialización
La serialización es el proceso de convertir un objeto en una secuencia de bytes para almacenarlo en disco o transmitirlo a través de una red. En el contexto de Scikit-Learn, es fundamental para persistir modelos y Pipelines entrenados, permitiendo su reutilización sin necesidad de reentrenamiento.
Existen dos herramientas principales en Python para la serialización: joblib
y pickle
. Ambas permiten guardar y cargar objetos, pero presentan diferencias en términos de eficiencia y uso práctico.
joblib
para serialización eficiente
La librería joblib
está diseñada para manejar de manera eficiente la serialización de objetos que contienen grandes arreglos de datos numpy. Es especialmente útil para guardar modelos y Pipelines de Scikit-Learn que suelen incluir matrices numéricas voluminosas.
Ventajas de joblib
:
- Eficiencia en el manejo de grandes cantidades de datos.
- Soporte de compresión, lo que reduce el espacio en disco.
- Mayor velocidad en el proceso de guardado y carga.
Ejemplo de uso de joblib
con compresión:
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression
from joblib import dump, Memory
# Configuración del almacenamiento en caché
memoria_cache = Memory(location='cache_directory', verbose=0)
# Creación del Pipeline con el parámetro "memory"
pipeline = Pipeline([
('escalado', StandardScaler()),
('regresion', LinearRegression())
], memory=memoria_cache)
# Entrenamiento del Pipeline
pipeline.fit(X_entrenamiento, y_entrenamiento)
# Guardado del Pipeline entrenado con compresión
dump(pipeline, 'pipeline_entrenado.joblib', compress=3)
En este ejemplo, el parámetro compress
indica el nivel de compresión, donde 3
es un equilibrio entre velocidad y compresión. La ruta cache_directory
es el directorio donde se almacenarán los datos en caché relacionados con el parámetro memory
.
pickle
para serialización general
El módulo estándar de Python pickle
permite la serialización y deserialización de objetos Python. Aunque es versátil, puede ser menos eficiente que joblib
con objetos de gran tamaño.
Ejemplo de uso de pickle
:
import pickle
# Guardado del Pipeline entrenado con pickle
with open('pipeline_entrenado.pkl', 'wb') as archivo:
pickle.dump(pipeline, archivo)
Es importante cerrar el archivo después del guardado para asegurar la integridad del archivo serializado.
Comparación entre joblib
y pickle
Aunque ambos métodos son válidos para persistir modelos, existen diferencias significativas:
- Rendimiento:
joblib
es más rápido y eficiente para objetos que contienen grandes arreglos numpy. - Compresión:
joblib
soporta compresión integrada, reduciendo el tamaño del archivo sin esfuerzo adicional. - Compatibilidad:
pickle
es una opción estándar y puede ser más compatible en diferentes entornos, pero puede ser menos eficiente.
Es recomendable utilizar joblib
al trabajar con modelos y Pipelines de Scikit-Learn debido a su optimización para este tipo de objetos.
Carga de objetos serializados
La carga de modelos se realiza de manera similar con ambos métodos.
Con joblib
:
from joblib import load
# Carga del Pipeline entrenado
pipeline_cargado = load('pipeline_entrenado.joblib')
# Realizar predicciones con el Pipeline cargado
predicciones = pipeline_cargado.predict(X_nuevos)
Con pickle
:
import pickle
# Carga del Pipeline entrenado con pickle
with open('pipeline_entrenado.pkl', 'rb') as archivo:
pipeline_cargado = pickle.load(archivo)
# Realizar predicciones con el Pipeline cargado
predicciones = pipeline_cargado.predict(X_nuevos)
Consideraciones al utilizar memory
en Pipelines
El parámetro memory
en un Pipeline permite almacenar en caché los resultados intermedios de las transformaciones, mejorando la eficiencia en procesos repetitivos como validaciones cruzadas o ajustes de hiperparámetros.
Al serializar un Pipeline que utiliza memory
, es crucial considerar:
- La ruta de caché debe existir en el entorno donde se cargue el Pipeline.
- Si cambia el entorno o se despliega en producción, es posible que se deba actualizar la ruta de
memory
.
Actualización de la ruta de caché después de cargar el Pipeline:
from joblib import Memory
# Carga del Pipeline entrenado
pipeline_cargado = load('pipeline_entrenado.joblib')
# Actualización de la ruta de caché
pipeline_cargado.memory = Memory(location='nueva_cache_directory', verbose=0)
# Realizar predicciones
predicciones = pipeline_cargado.predict(X_nuevos)
Mejores prácticas en serialización
- Versiones consistentes: Asegurar que las versiones de Python y Scikit-Learn sean compatibles entre el momento de guardado y carga para evitar errores.
- Funciones personalizadas: Si el Pipeline contiene transformadores o funciones definidos por el usuario, deben estar disponibles en el entorno al cargar el objeto serializado.
- Seguridad: Evitar cargar archivos de orígenes desconocidos, ya que la deserialización puede ejecutar código malicioso.
Serialización de Pipelines con transformadores personalizados
Al emplear transformadores personalizados en un Pipeline, es esencial que su definición sea accesible durante la deserialización.
Ejemplo de un transformador personalizado:
from sklearn.base import TransformerMixin, BaseEstimator
from sklearn.pipeline import Pipeline
from joblib import dump, Memory
class TransformadorPersonalizado(BaseEstimator, TransformerMixin):
def fit(self, X, y=None):
# Lógica del ajuste
return self
def transform(self, X):
# Lógica de transformación
return X_transformado
# Configuración del almacenamiento en caché
memoria_cache = Memory(location='cache_directory', verbose=0)
# Creación del Pipeline con el transformador personalizado
pipeline = Pipeline([
('transformador', TransformadorPersonalizado()),
('modelo', LinearRegression())
], memory=memoria_cache)
# Entrenamiento del Pipeline
pipeline.fit(X_entrenamiento, y_entrenamiento)
# Guardado del Pipeline entrenado
dump(pipeline, 'pipeline_personalizado.joblib')
Al cargar este Pipeline, se debe importar o definir la clase TransformadorPersonalizado
en el entorno actual:
from joblib import load
# Definición o importación del transformador personalizado
class TransformadorPersonalizado(BaseEstimator, TransformerMixin):
def fit(self, X, y=None):
# Lógica del ajuste
return self
def transform(self, X):
# Lógica de transformación
return X_transformado
# Carga del Pipeline entrenado
pipeline_cargado = load('pipeline_personalizado.joblib')
# Uso del Pipeline cargado
predicciones = pipeline_cargado.predict(X_nuevos)
Consejos adicionales
- Compresión adecuada: Ajustar el nivel de compresión en
joblib
según las necesidades. Un nivel más alto reduce el tamaño del archivo pero puede aumentar el tiempo de guardado y carga. - Organización de archivos: Mantener una estructura clara de los archivos serializados y las rutas de caché para facilitar el mantenimiento y despliegue.
- Documentación: Anotar las versiones de las librerías y dependencias utilizadas al entrenar y guardar el Pipeline para futuras referencias.
Con una comprensión profunda de joblib
y pickle
, se pueden implementar estrategias de serialización efectivas que optimicen el flujo de trabajo y aseguren la portabilidad de los modelos entrenados.
Consideraciones al desplegar Pipelines en producción
El despliegue de Pipelines de Scikit-Learn en un entorno de producción requiere atención a varios aspectos para garantizar su correcto funcionamiento y mantener la integridad del sistema. A continuación, se presentan las principales consideraciones al llevar un Pipeline entrenado a producción.
Primero, es crucial asegurar la consistencia del entorno. Las versiones de Python, Scikit-Learn y demás dependencias deben coincidir entre el entorno de entrenamiento y el de producción. Diferencias en las versiones pueden causar incompatibilidades y errores inesperados.
Para lograr entornos consistentes, es recomendable utilizar entornos virtuales o contenedores como Docker. Estos permiten definir un entorno aislado con todas las dependencias necesarias:
FROM python:3.13
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "app.py"]
Es fundamental especificar las versiones exactas de las librerías en el archivo requirements.txt
:
scikit-learn==1.5.2
numpy==2.2.1
pandas==2.1.0
joblib==1.4.0
En cuanto a la seguridad, se debe evitar cargar modelos desde fuentes no confiables. La deserialización con pickle
o joblib
puede ejecutar código malicioso si el archivo ha sido manipulado. Siempre cargar modelos verificados y controlar los permisos de acceso al sistema de archivos.
La gestión de recursos es otro aspecto clave. En producción, es importante optimizar el uso de CPU y memoria. Si el Pipeline incluye algoritmos que soportan paralelización, utilizar el parámetro n_jobs=-1
para aprovechar todos los núcleos disponibles:
from sklearn.pipeline import Pipeline
from sklearn.ensemble import RandomForestClassifier
from joblib import load, Memory
# Configuración del almacenamiento en caché
memoria_cache = Memory(location='cache_produccion', verbose=0)
# Creación del Pipeline con el parámetro "memory"
pipeline = Pipeline([
('transformacion', TransformadorPersonalizado()),
('clasificador', RandomForestClassifier(n_jobs=-1))
], memory=memoria_cache)
# Carga del Pipeline entrenado
pipeline = load('pipeline_entrenado.joblib')
# Predicción con nuevos datos
predicciones = pipeline.predict(X_nuevos)
Implementar un sistema de monitorización y logging es esencial para detectar posibles problemas en tiempo real. Registrar métricas como tiempos de respuesta, tasas de error y estadísticas de uso ayuda a mantener el rendimiento óptimo del Pipeline.
Es importante considerar la validación de datos en producción. Los datos recibidos pueden diferir de los usados durante el entrenamiento, por lo que es vital implementar chequeos para asegurar que cumplen con el formato y las características esperadas. Esto puede incluir verificación de tipos de datos, rangos de valores y estructura de las entradas.
La escalabilidad del sistema debe ser evaluada para garantizar que puede manejar el volumen de solicitudes esperado. Si se prevé un alto número de predicciones, considerar el uso de servicios de orquestación y escalado automático como Kubernetes, o servicios gestionados en la nube.
Cuando se despliegan Pipelines que incluyen transformadores o componentes personalizados, es imprescindible que todas las dependencias estén disponibles en el entorno de producción. Utilizar herramientas de gestión de paquetes y control de versiones como Git y configurar CI/CD permite que los cambios se integren de manera controlada y reproducible.
El manejo de actualizaciones del modelo es otro aspecto a tener en cuenta. Para minimizar el impacto en el servicio, se pueden implementar estrategias como el despliegue de versiones paralelas del modelo y el encaminamiento gradual del tráfico (blue-green deployment). Esto facilita la transición a nuevas versiones sin interrumpir la operación.
Por último, es recomendable documentar exhaustivamente el Pipeline y los procesos asociados. Una documentación clara facilita el mantenimiento y la colaboración entre equipos, asegurando que cualquier miembro pueda entender y gestionar el sistema en producción.
Actualización y mantenimiento de Pipelines guardados
El mantenimiento y actualización de Pipelines guardados es esencial para asegurar que los modelos sigan siendo efectivos y relevantes a lo largo del tiempo. A medida que se disponen de nuevos datos o cambian los requisitos del negocio, es necesario adaptar los Pipelines existentes para reflejar estos cambios.
Para actualizar un Pipeline con nuevos datos, se puede cargar el Pipeline guardado y reentrenarlo con el conjunto de datos ampliado. Esto permite reutilizar las transformaciones y los hiperparámetros previamente definidos, asegurando la consistencia en el procesamiento de los datos.
from joblib import load, dump, Memory
# Configuración del almacenamiento en caché
memoria_cache = Memory(location='ruta_cache', verbose=0)
# Carga del Pipeline guardado
pipeline = load('pipeline_entrenado.joblib')
# Actualización de la ruta de caché
pipeline.memory = memoria_cache
# Reentrenamiento del Pipeline con nuevos datos
pipeline.fit(X_nuevo_entrenamiento, y_nuevo_entrenamiento)
# Guardado del Pipeline actualizado
dump(pipeline, 'pipeline_actualizado.joblib')
En este ejemplo, se carga el Pipeline previamente guardado y se asigna una nueva ruta para el parámetro memory
. Luego, se reentrena el Pipeline utilizando los nuevos datos disponibles y se guarda nuevamente en disco para su posterior utilización.
Es recomendable implementar un sistema de versionado para los Pipelines, permitiendo llevar un control de los cambios y actualizaciones realizadas. Esto se puede lograr mediante la nomenclatura de los archivos o utilizando herramientas especializadas como DVC (Data Version Control). Mantener un historial de versiones facilita el retorno a configuraciones anteriores en caso de problemas.
Cuando se incorporan nuevos pasos o transformaciones al Pipeline, es importante asegurar la compatibilidad con el modelo existente. Añadir o modificar etapas de preprocesamiento puede afectar al rendimiento y a la interpretación del modelo. Se debe evaluar cuidadosamente el impacto de estos cambios y considerar reentrenar el modelo completo.
from sklearn.decomposition import PCA
from sklearn.pipeline import Pipeline
# Añadir un nuevo transformador al Pipeline existente
pasos = pipeline.steps
# Insertar PCA antes del modelo
pasos_nuevos = pasos[:-1] + [('pca', PCA(n_components=5))] + [pasos[-1]]
# Crear un nuevo Pipeline con los pasos actualizados
pipeline_actualizado = Pipeline(steps=pasos_nuevos, memory=memoria_cache)
# Reentrenamiento del Pipeline con los nuevos pasos
pipeline_actualizado.fit(X_nuevo_entrenamiento, y_nuevo_entrenamiento)
# Guardado del Pipeline actualizado
dump(pipeline_actualizado, 'pipeline_actualizado.joblib')
En este código, se extraen los pasos del Pipeline original y se inserta un nuevo transformador PCA antes del modelo. Luego, se crea un nuevo Pipeline con los pasos actualizados y se reentrena con los datos nuevos. Esto permite extender el Pipeline manteniendo la estructura previa.
Al actualizar las versiones de las librerías, como Scikit-Learn, pueden surgir problemas de compatibilidad con los Pipelines guardados. Es esencial verificar que las nuevas versiones son compatibles y, de ser necesario, adaptar el código para cumplir con las nuevas APIs o funcionalidades. Mantener un registro de las versiones de las dependencias en un archivo como requirements.txt
ayuda a prevenir conflictos.
El monitoreo continuo del rendimiento del modelo en producción es clave para determinar cuándo es necesaria una actualización. Si se detecta que la precisión del modelo disminuye con el tiempo, puede ser indicativo de cambios en los datos o en los patrones que el modelo debe capturar. En estos casos, reentrenar el modelo con datos más recientes puede restaurar su eficacia.
Implementar pruebas automatizadas y validación del modelo después de cada actualización garantiza que el Pipeline sigue funcionando correctamente. Las pruebas pueden incluir la verificación de las métricas de rendimiento, la integridad de las transformaciones y la capacidad de manejar excepciones o datos atípicos.
Para facilitar el mantenimiento, es recomendable documentar detalladamente el Pipeline, incluyendo la descripción de cada paso, los hiperparámetros utilizados y cualquier consideración especial. Una documentación clara ayuda a otros miembros del equipo a entender y gestionar el modelo, especialmente en entornos colaborativos.
En entornos de producción, donde la estabilidad es crítica, se pueden implementar estrategias de despliegue continuo con sistemas de integración continua (CI/CD). Esto permite automatizar el proceso de actualización del Pipeline, incluyendo reentrenamiento, pruebas y despliegue, reduciendo errores y tiempos de inactividad.
Finalmente, considerar el uso de técnicas de orquestación y gestión de modelos como MLflow o Kubeflow puede simplificar el proceso de actualización y mantenimiento de Pipelines guardados, proporcionando herramientas para el seguimiento de experimentos, gestión de modelos y despliegue escalable.
Ejercicios de esta lección Exportar e importar Pipelines
Evalúa tus conocimientos de esta lección Exportar e importar Pipelines con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.
Todas las lecciones de ScikitLearn
Accede a todas las lecciones de ScikitLearn y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.
Aprendizaje Automático
Introducción Y Entorno
Introducción E Instalación
Introducción Y Entorno
Introducción Al Preprocesamiento De Datos
Preprocesamiento De Datos
Identificación Y Tratamiento De Valores Faltantes
Preprocesamiento De Datos
Escalado De Datos
Preprocesamiento De Datos
Normalización De Datos
Preprocesamiento De Datos
Codificación De Variables Categóricas
Preprocesamiento De Datos
Ingeniería De Características
Preprocesamiento De Datos
Selección De Características
Preprocesamiento De Datos
Extracción De Características
Preprocesamiento De Datos
Particionamiento De Datos
Preprocesamiento De Datos
Preprocesamiento De Datos Desbalanceados
Preprocesamiento De Datos
Introducción A La Regresión
Regresión
Regresión Lineal
Regresión
Regresión Knn Kneighborsregressor
Regresión
Regresión Svm Con Svr
Regresión
Regresión Con Árboles Decisiontreeregressor
Regresión
Regresión Con Algoritmos De Conjunto
Regresión
Introducción A La Clasificación
Clasificación
Clasificación Con Regresión Logística
Clasificación
Clasificación Knn Kneighborsclassifier
Clasificación
Clasificación Svm Con Svc
Clasificación
Clasificación Con Árboles Decisiontreeclassifier
Clasificación
Clasificación Con Algoritmos De Conjunto
Clasificación
Reducción De La Dimensionalidad Con Pca
Aprendizaje No Supervisado
Clustering Con Kmeans
Aprendizaje No Supervisado
Clustering Jerárquico
Aprendizaje No Supervisado
Clustering De Densidad Con Dbscan
Aprendizaje No Supervisado
Preprocesamiento De Textos Para Nlp
Nlp
Representación De Texto Y Extracción De Características
Nlp
Clasificación De Texto Con Scikit Learn
Nlp
Análisis De Sentimiento
Nlp
Técnicas Avanzadas De Extracción De Características
Nlp
Introducción Al Análisis De Series Temporales
Series Temporales
Preprocesamiento De Datos De Series Temporales
Series Temporales
Ingeniería De Características Para Series Temporales
Series Temporales
Transformación Y Escalado De Series Temporales
Series Temporales
Validación Y Evaluación De Modelos En Series Temporales
Series Temporales
Validación Y Evaluación De Modelos
Validación De Modelos
Técnicas De Validación Cruzada
Validación De Modelos
Métricas De Regresión
Validación De Modelos
Métricas De Clasificación
Validación De Modelos
Ajuste De Hiperparámetros
Validación De Modelos
Introducción A Pipelines
Pipelines Y Despliegue
Creación De Pipelines Básicos
Pipelines Y Despliegue
Preprocesamiento De Datos Con Pipelines
Pipelines Y Despliegue
Pipelines Y Validación Cruzada
Pipelines Y Despliegue
Pipelines Con Columntransformer
Pipelines Y Despliegue
Exportar E Importar Pipelines
Pipelines Y Despliegue
Objetivos de aprendizaje de esta lección
- Comprender la importancia de serializar Pipelines entrenados.
- Aprender a usar joblib y pickle para guardar y cargar modelos.
- Conocer las consideraciones de compatibilidad y seguridad al cargar modelos.
- Aplicar técnicas para manejar actualizaciones y mantenimiento de Pipelines.