🎯 Objetivo del Post: Aprenderás a llevar tu modelo desde el notebook de desarrollo hasta un sistema en producción, incluyendo despliegue, monitoreo y mejores prácticas profesionales.
🚀 ¿Qué Significa "Usar el Modelo"?
Después de todo el trabajo de preparación de datos, entrenamiento y optimización, llega el momento más emocionante: usar nuestro modelo para hacer predicciones reales. Pero usar un modelo no es solo hacer model.predict()
. Implica un proceso completo de despliegue, monitoreo y mantenimiento.
💡 Definición Profesional: Usar el modelo significa integrarlo en un sistema que pueda tomar decisiones basadas en predicciones automáticas, de manera confiable y escalable.
🔄 Del Notebook al Mundo Real
📝 En el Notebook (Desarrollo)
# Esto es lo que hemos estado haciendo (simple pero funcional)
modelo = Ridge(alpha=10)
modelo.fit(X_train, y_train)
prediccion = modelo.predict(X_nuevo)
print(f"Precio predicho: ${prediccion[0]:,.2f}")
🌍 En Producción (Mundo Real)
# Esto es lo que necesitamos para usar el modelo realmente (robusto y escalable)
class PrediccionPreciosAutos:
def __init__(self):
self.modelo = None
self.scaler = None
self.columnas_esperadas = None
def cargar_modelo(self, ruta_modelo, ruta_scaler):
"""Cargar modelo y preprocesador desde archivos"""
import pickle
with open(ruta_modelo, 'rb') as f:
self.modelo = pickle.load(f)
with open(ruta_scaler, 'rb') as f:
self.scaler = pickle.load(f)
# Cargar información de columnas
with open('columnas_esperadas.pkl', 'rb') as f:
self.columnas_esperadas = pickle.load(f)
def predecir_precio(self, datos_auto):
"""Predecir precio de un auto específico"""
# Validar entrada
if not self._validar_entrada(datos_auto):
return None
# Preparar datos
datos_procesados = self._procesar_entrada(datos_auto)
# Hacer predicción
prediccion = self.modelo.predict(datos_procesados)
return {
'precio_predicho': float(prediccion[0]),
'confianza': self._calcular_confianza(datos_procesados),
'fecha_prediccion': datetime.now().isoformat()
}
Tipos de Uso del Modelo
1. Predicción Individual (One-off)
Para predecir el precio de un auto específico:
# Datos de un auto específico
auto_ejemplo = {
'marca': 'BMW',
'modelo': '3 Series',
'año': 2020,
'kilometraje': 25000,
'transmision': 'AUTOMATIC',
'engine_hp': 255,
'engine_cylinders': 4
}
# Usar el modelo
prediccion = modelo.predict(auto_ejemplo)
print(f"Precio estimado: ${prediccion:,.2f}")
2. Predicción por Lotes (Batch)
Para procesar múltiples autos a la vez:
# Lista de autos
autos_lote = [
{'marca': 'Toyota', 'modelo': 'Camry', 'año': 2019, 'kilometraje': 30000},
{'marca': 'Honda', 'modelo': 'Civic', 'año': 2021, 'kilometraje': 15000},
{'marca': 'BMW', 'modelo': 'X5', 'año': 2020, 'kilometraje': 20000}
]
# Procesar lote
predicciones = []
for auto in autos_lote:
precio = modelo.predict(auto)
predicciones.append({
'auto': f"{auto['marca']} {auto['modelo']}",
'precio_predicho': precio
})
# Crear DataFrame con resultados
resultados = pd.DataFrame(predicciones)
print(resultados)
3. API Web (Tiempo Real)
Crear una API para que otros sistemas puedan usar nuestro modelo:
from flask import Flask, request, jsonify
import pickle
import pandas as pd
app = Flask(__name__)
# Cargar modelo al iniciar la aplicación
with open('modelo_entrenado.pkl', 'rb') as f:
modelo = pickle.load(f)
@app.route('/predict', methods=['POST'])
def predecir_precio():
"""Endpoint para predecir precio de auto"""
try:
# Obtener datos del request
datos = request.json
# Validar datos requeridos
campos_requeridos = ['marca', 'modelo', 'año', 'kilometraje']
for campo in campos_requeridos:
if campo not in datos:
return jsonify({'error': f'Campo {campo} es requerido'}), 400
# Preparar datos para el modelo
datos_modelo = pd.DataFrame([datos])
# Hacer predicción
precio_predicho = modelo.predict(datos_modelo)[0]
# Devolver resultado
return jsonify({
'precio_predicho': float(precio_predicho),
'status': 'success'
})
except Exception as e:
return jsonify({'error': str(e)}), 500
if __name__ == '__main__':
app.run(debug=True)
Guardando y Cargando el Modelo
Guardar el Modelo Entrenado
import pickle
import joblib
# Opción 1: Usando pickle
with open('modelo_precios_autos.pkl', 'wb') as f:
pickle.dump(modelo, f)
# Opción 2: Usando joblib (más eficiente para modelos grandes)
joblib.dump(modelo, 'modelo_precios_autos.joblib')
# Guardar también el scaler y las columnas
joblib.dump(scaler, 'scaler.joblib')
joblib.dump(list(X.columns), 'columnas_esperadas.joblib')
print("Modelo guardado exitosamente")
Cargar el Modelo
# Cargar modelo
modelo_cargado = joblib.load('modelo_precios_autos.joblib')
scaler_cargado = joblib.load('scaler.joblib')
columnas_esperadas = joblib.load('columnas_esperadas.joblib')
# Usar el modelo cargado
def predecir_con_modelo_cargado(datos_auto):
# Convertir a DataFrame
df_auto = pd.DataFrame([datos_auto])
# Asegurar que tiene las columnas correctas
for columna in columnas_esperadas:
if columna not in df_auto.columns:
df_auto[columna] = 0 # Valor por defecto
# Reordenar columnas
df_auto = df_auto[columnas_esperadas]
# Normalizar
df_auto_scaled = scaler_cargado.transform(df_auto)
# Predecir
precio = modelo_cargado.predict(df_auto_scaled)[0]
return precio
# Ejemplo de uso
auto_nuevo = {
'marca_BMW': 1,
'marca_Toyota': 0,
'año': 2020,
'kilometraje': 25000,
'engine_hp': 255
}
precio = predecir_con_modelo_cargado(auto_nuevo)
print(f"Precio predicho: ${precio:,.2f}")
Validación de Entrada
Validar Datos Antes de Predecir
class ValidadorDatos:
@staticmethod
def validar_auto(datos_auto):
"""Validar que los datos del auto sean correctos"""
errores = []
# Validar año
if 'año' in datos_auto:
año = datos_auto['año']
if not isinstance(año, (int, float)) or año < 1990 or año > 2024:
errores.append("Año debe ser un número entre 1990 y 2024")
# Validar kilometraje
if 'kilometraje' in datos_auto:
km = datos_auto['kilometraje']
if not isinstance(km, (int, float)) or km < 0 or km > 500000:
errores.append("Kilometraje debe ser un número positivo menor a 500,000")
# Validar marca
marcas_validas = ['BMW', 'Toyota', 'Honda', 'Audi', 'Mercedes-Benz']
if 'marca' in datos_auto:
if datos_auto['marca'] not in marcas_validas:
errores.append(f"Marca debe ser una de: {', '.join(marcas_validas)}")
return errores
# Usar validador
validador = ValidadorDatos()
datos_auto = {
'marca': 'BMW',
'año': 2020,
'kilometraje': 25000
}
errores = validador.validar_auto(datos_auto)
if errores:
print("Errores encontrados:")
for error in errores:
print(f"- {error}")
else:
print("Datos válidos, procediendo con predicción")
precio = predecir_con_modelo_cargado(datos_auto)
print(f"Precio predicho: ${precio:,.2f}")
Monitoreo del Modelo
Tracking de Predicciones
import logging
from datetime import datetime
# Configurar logging
logging.basicConfig(
filename='predicciones.log',
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
class MonitorModelo:
def __init__(self):
self.predicciones_dia = 0
self.predicciones_totales = 0
def registrar_prediccion(self, datos_entrada, prediccion, confianza=None):
"""Registrar una predicción para monitoreo"""
timestamp = datetime.now()
# Incrementar contadores
self.predicciones_totales += 1
if timestamp.date() == datetime.now().date():
self.predicciones_dia += 1
# Log de la predicción
log_info = {
'timestamp': timestamp.isoformat(),
'datos_entrada': datos_entrada,
'prediccion': float(prediccion),
'confianza': confianza
}
logging.info(f"Predicción realizada: {log_info}")
return log_info
def obtener_estadisticas(self):
"""Obtener estadísticas del modelo"""
return {
'predicciones_totales': self.predicciones_totales,
'predicciones_hoy': self.predicciones_dia,
'fecha_ultimo_uso': datetime.now().isoformat()
}
# Usar monitor
monitor = MonitorModelo()
def predecir_con_monitoreo(datos_auto):
# Hacer predicción
precio = predecir_con_modelo_cargado(datos_auto)
# Registrar en monitor
monitor.registrar_prediccion(datos_auto, precio)
return precio
# Ejemplo de uso
auto = {'marca': 'BMW', 'año': 2020, 'kilometraje': 25000}
precio = predecir_con_monitoreo(auto)
print(f"Precio: ${precio:,.2f}")
print(f"Estadísticas: {monitor.obtener_estadisticas()}")
Interfaz de Usuario Simple
Aplicación Web Básica
import streamlit as st
import pandas as pd
# Configurar página
st.set_page_config(page_title="Predicción de Precios de Autos", page_icon="🚗")
st.title("🚗 Predicción de Precios de Autos")
st.markdown("Ingresa las características de tu auto para obtener una estimación de precio")
# Formulario de entrada
with st.form("form_prediccion"):
col1, col2 = st.columns(2)
with col1:
marca = st.selectbox("Marca", ["BMW", "Toyota", "Honda", "Audi", "Mercedes-Benz"])
año = st.number_input("Año", min_value=1990, max_value=2024, value=2020)
kilometraje = st.number_input("Kilometraje", min_value=0, max_value=500000, value=25000)
with col2:
modelo = st.text_input("Modelo", value="3 Series")
transmision = st.selectbox("Transmisión", ["MANUAL", "AUTOMATIC", "AUTOMATED_MANUAL"])
engine_hp = st.number_input("Potencia del Motor (HP)", min_value=50, max_value=700, value=255)
submitted = st.form_submit_button("Predecir Precio")
if submitted:
# Preparar datos
datos_auto = {
'marca': marca,
'modelo': modelo,
'año': año,
'kilometraje': kilometraje,
'transmision': transmision,
'engine_hp': engine_hp
}
# Hacer predicción
try:
precio = predecir_con_modelo_cargado(datos_auto)
# Mostrar resultado
st.success(f"💰 Precio estimado: **${precio:,.2f}**")
# Mostrar detalles
with st.expander("Ver detalles de la predicción"):
st.json(datos_auto)
except Exception as e:
st.error(f"Error al hacer predicción: {str(e)}")
# Estadísticas del modelo
st.sidebar.title("📊 Estadísticas del Modelo")
estadisticas = monitor.obtener_estadisticas()
st.sidebar.metric("Predicciones Totales", estadisticas['predicciones_totales'])
st.sidebar.metric("Predicciones Hoy", estadisticas['predicciones_hoy'])
Mejores Prácticas para Usar el Modelo
1. Manejo de Errores Robusto
def predecir_seguro(datos_auto):
try:
# Validar entrada
errores = ValidadorDatos.validar_auto(datos_auto)
if errores:
return {'error': 'Datos inválidos', 'detalles': errores}
# Hacer predicción
precio = predecir_con_modelo_cargado(datos_auto)
return {'precio': precio, 'status': 'success'}
except Exception as e:
logging.error(f"Error en predicción: {str(e)}")
return {'error': 'Error interno del servidor', 'status': 'error'}
2. Versionado del Modelo
# Guardar modelo con versión
version = "v1.0"
joblib.dump(modelo, f'modelo_precios_autos_{version}.joblib')
# Cargar modelo específico
def cargar_modelo_version(version):
return joblib.load(f'modelo_precios_autos_{version}.joblib')
3. Configuración Flexible
# Archivo config.yaml
model_config = {
'model_path': 'modelo_precios_autos_v1.0.joblib',
'scaler_path': 'scaler_v1.0.joblib',
'max_price': 200000,
'min_price': 1000,
'confidence_threshold': 0.7
}
Errores Comunes al Usar el Modelo
1. Olvidar el Preprocesamiento
# MAL: Usar datos sin preprocesar
precio = modelo.predict(datos_sin_procesar)
# BIEN: Aplicar el mismo preprocesamiento del entrenamiento
datos_procesados = scaler.transform(datos_sin_procesar)
precio = modelo.predict(datos_procesados)
2. No Validar Entrada
# MAL: Confiar en que los datos son correctos
precio = modelo.predict(datos_usuario)
# BIEN: Validar primero
if validar_datos(datos_usuario):
precio = modelo.predict(datos_usuario)
else:
return error
3. Ignorar el Monitoreo
# MAL: No registrar predicciones
precio = modelo.predict(datos)
# BIEN: Registrar para monitoreo
precio = modelo.predict(datos)
monitor.registrar_prediccion(datos, precio)
Conclusión
Usar el modelo en producción va mucho más allá de hacer predicciones. Requiere:
- Preparación cuidadosa: Guardar y cargar modelos correctamente
- Validación robusta: Verificar datos de entrada
- Monitoreo continuo: Rastrear el rendimiento del modelo
- Manejo de errores: Prepararse para situaciones inesperadas
- Interfaces amigables: Hacer el modelo accesible a usuarios finales
Puntos clave:
- El modelo debe ser fácil de usar pero seguro
- Siempre validar datos de entrada
- Monitorear el rendimiento continuamente
- Preparar interfaces para diferentes tipos de usuarios
- Documentar todo el proceso de uso
¡Has completado todo el ciclo de Machine Learning! Desde la preparación de datos hasta el despliegue del modelo en producción. Ahora tienes las herramientas para crear sistemas de ML que realmente funcionen en el mundo real.
¿Has desplegado algún modelo en producción? ¿Qué desafíos has encontrado al usar modelos en el mundo real?
Top comments (0)