# MLflow

**MLflow** es una plataforma de código abierto para gestionar el completo **ciclo de vida de Machine Learning** — desde el seguimiento de experimentos y el versionado de modelos hasta el despliegue y la monitorización. Usado por miles de organizaciones en todo el mundo, MLflow aporta estructura y reproducibilidad a los flujos de trabajo de ML. Ejecútalo en la nube GPU de Clore.ai para obtener un servidor de seguimiento centralizado junto a tus trabajos de entrenamiento.

***

## ¿Qué es MLflow?

MLflow proporciona cuatro componentes principales:

| Componente              | Descripción                                                             |
| ----------------------- | ----------------------------------------------------------------------- |
| **Seguimiento**         | Registra parámetros, métricas, artefactos y código de ejecuciones de ML |
| **Proyectos**           | Empaquetar código para ejecuciones reproducibles                        |
| **Modelos**             | Formato estándar de modelo para despliegue entre frameworks             |
| **Registro de Modelos** | Almacén centralizado de modelos con versionado y ciclo de vida          |

**Frameworks compatibles (autologging incorporado):**

* PyTorch, TensorFlow/Keras
* Scikit-learn, XGBoost, LightGBM
* HuggingFace Transformers
* Spark MLlib, statsmodels, Prophet

***

## Prerrequisitos

| Requisito      | Valor                                                       |
| -------------- | ----------------------------------------------------------- |
| VRAM GPU       | Cualquiera (el servidor MLflow en sí está limitado por CPU) |
| Almacenamiento | 20 GB+ (para artefactos)                                    |
| RAM            | 4 GB mínimo para el servidor                                |
| Puertos        | 22 (SSH), 5000 (Interfaz MLflow)                            |

{% hint style="info" %}
El servidor de seguimiento de MLflow es ligero. Puedes ejecutarlo en una instancia CPU pequeña y apuntar tus trabajos de entrenamiento en GPU hacia él. Alternativamente, ubícalo en la misma instancia GPU de entrenamiento.
{% endhint %}

***

## Paso 1 — Alquilar un servidor en Clore.ai

1. Inicia sesión en [clore.ai](https://clore.ai).
2. Haz clic **Marketplace**.
3. Para un servidor de seguimiento dedicado: filtra por RAM ≥ 8 GB (GPU opcional).
4. Para co-ubicado: usa tu instancia de entrenamiento existente.
5. Establecer imagen Docker: **`ghcr.io/mlflow/mlflow:latest`**
6. Establecer puertos abiertos: `22` (SSH) y `5000` (Interfaz MLflow).
7. Haz clic **Alquilar**.

***

## Paso 2 — Lanzar el Servidor de Seguimiento MLflow

El oficial `ghcr.io/mlflow/mlflow` la imagen requiere anular el comando de inicio.

### En la Configuración de Docker de Clore.ai

Configura el **comando** (o anulación del entrypoint) a:

```bash
bash -c "apt-get update -q && apt-get install -y -q openssh-server && \
    mkdir /var/run/sshd && \
    echo 'root:clore123' | chpasswd && \
    sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config && \
    service ssh start && \
    mlflow server \
        --host 0.0.0.0 \
        --port 5000 \
        --default-artifact-root /mlflow/artifacts \
        --backend-store-uri sqlite:////mlflow/mlflow.db"
```

### Alternativa: Dockerfile Personalizado

```dockerfile
FROM ghcr.io/mlflow/mlflow:latest

RUN apt-get update && apt-get install -y \
    openssh-server \
    && rm -rf /var/lib/apt/lists/*

# Configurar SSH
RUN mkdir /var/run/sshd && \
    echo 'root:clore123' | chpasswd && \
    sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config

# Paquetes adicionales de Python
RUN pip install boto3 psycopg2-binary

RUN mkdir -p /mlflow/artifacts

EXPOSE 22 5000

CMD service ssh start && \
    mlflow server \
        --host 0.0.0.0 \
        --port 5000 \
        --default-artifact-root /mlflow/artifacts \
        --backend-store-uri sqlite:////mlflow/mlflow.db
```

***

## Paso 3 — Acceder a la Interfaz MLflow

Abre tu navegador:

```
http://<clore-host>:<public-port-5000>
```

Deberías ver el panel de Experimentos de MLflow.

{% hint style="info" %}
El backend SQLite por defecto (`mlflow.db`) almacena todos los metadatos de las ejecuciones localmente. Para uso en producción o en equipo, cambia a PostgreSQL — consulta la Configuración Avanzada abajo.
{% endhint %}

***

## Paso 4 — Registra Tu Primer Experimento

### Conectar desde un Trabajo de Entrenamiento Remoto

En tu máquina de entrenamiento (u otra instancia de Clore.ai), establece el URI de seguimiento:

```bash
export MLFLOW_TRACKING_URI=http://<clore-host>:<public-port-5000>
```

### Registro básico de experimentos con PyTorch

```python
import mlflow
import mlflow.pytorch
import torch
import torch.nn as nn
import torch.optim as optim

# Conectar al servidor MLflow
mlflow.set_tracking_uri("http://<clore-host>:<public-port-5000>")
mlflow.set_experiment("my-first-experiment")

# Definir un modelo simple
class SimpleNet(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super().__init__()
        self.fc1 = nn.Linear(input_size, hidden_size)
        self.relu = nn.ReLU()
        self.fc2 = nn.Linear(hidden_size, output_size)
    
    def forward(self, x):
        return self.fc2(self.relu(self.fc1(x)))

# Entrenamiento con seguimiento MLflow
with mlflow.start_run(run_name="training-run-001"):
    # Registrar hiperparámetros
    params = {
        "learning_rate": 0.001,
        "batch_size": 64,
        "epochs": 100,
        "hidden_size": 256,
        "optimizer": "adam"
    }
    mlflow.log_params(params)
    
    # Inicializar modelo
    model = SimpleNet(784, 256, 10).cuda()
    optimizer = optim.Adam(model.parameters(), lr=params["learning_rate"])
    criterion = nn.CrossEntropyLoss()
    
    # Bucle de entrenamiento
    for epoch in range(params["epochs"]):
        loss = torch.tensor(0.5 / (epoch + 1))  # Simulado
        accuracy = 0.7 + epoch * 0.003
        
        # Registrar métricas en cada época
        mlflow.log_metrics({
            "train_loss": loss.item(),
            "train_accuracy": accuracy,
        }, step=epoch)
    
    # Registrar el modelo final
    mlflow.pytorch.log_model(model, "model")
    
    # Registrar métricas finales
    mlflow.log_metric("final_accuracy", accuracy)
    
    print(f"Run logged to MLflow. ID: {mlflow.active_run().info.run_id}")
```

### Autoregistro de HuggingFace Transformers

```python
import mlflow
from transformers import TrainingArguments, Trainer

mlflow.set_tracking_uri("http://<clore-host>:<public-port-5000>")
mlflow.set_experiment("llm-finetuning")

# Habilitar autologging — registra automáticamente params, métricas y modelo
mlflow.transformers.autolog()

training_args = TrainingArguments(
    output_dir="./results",
    num_train_epochs=3,
    per_device_train_batch_size=16,
    per_device_eval_batch_size=64,
    learning_rate=2e-5,
    warmup_steps=500,
    weight_decay=0.01,
    logging_dir="./logs",
    logging_steps=10,
    evaluation_strategy="epoch",
)

trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=train_dataset,
    eval_dataset=eval_dataset,
)

with mlflow.start_run():
    trainer.train()
```

***

## Paso 5 — Scikit-learn con Autologging

```python
import mlflow
import mlflow.sklearn
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_digits

mlflow.set_tracking_uri("http://<clore-host>:<public-port-5000>")
mlflow.set_experiment("sklearn-experiments")

# Autoregistra todo
mlflow.sklearn.autolog()

X, y = load_digits(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

with mlflow.start_run(run_name="random-forest-v1"):
    rf = RandomForestClassifier(n_estimators=100, max_depth=10, random_state=42)
    rf.fit(X_train, y_train)
    
    score = rf.score(X_test, y_test)
    print(f"Test Accuracy: {score:.4f}")
    # ¡Todos los parámetros, métricas y el modelo se registran automáticamente!
```

***

## Paso 6 — Registro de Modelos

Registra y gestiona versiones de modelos mediante la UI o la API:

```python
import mlflow

client = mlflow.MlflowClient("http://<clore-host>:<public-port-5000>")

# Registrar un modelo desde una ejecución
run_id = "your-run-id-here"
model_uri = f"runs:/{run_id}/model"

registered = mlflow.register_model(
    model_uri=model_uri,
    name="production-classifier"
)

print(f"Version: {registered.version}")

# Transicionar la etapa del modelo
client.transition_model_version_stage(
    name="production-classifier",
    version=registered.version,
    stage="Production"
)

# Cargar un modelo en producción en cualquier lugar
model = mlflow.pyfunc.load_model(
    model_uri="models:/production-classifier/Production"
)
```

***

## Paso 7 — Servir un Modelo

MLflow puede servir cualquier modelo registrado como una API REST:

```bash
# En la instancia del servidor MLflow
export MLFLOW_TRACKING_URI=http://localhost:5000

mlflow models serve \
    --model-uri "models:/production-classifier/Production" \
    --host 0.0.0.0 \
    --port 5001 \
    --no-conda
```

Probar el modelo servido:

```bash
curl -X POST http://<clore-host>:5001/invocations \
    -H "Content-Type: application/json" \
    -d '{"inputs": [[1.0, 2.0, 3.0, ...]]}'
```

***

## Configuración avanzada

### Backend PostgreSQL (Producción)

```bash
# Lanzar con PostgreSQL
mlflow server \
    --host 0.0.0.0 \
    --port 5000 \
    --backend-store-uri postgresql://user:password@db-host/mlflow \
    --default-artifact-root s3://my-bucket/mlflow-artifacts
```

### Almacén de Artefactos S3

```bash
pip install boto3

export AWS_ACCESS_KEY_ID=your_key
export AWS_SECRET_ACCESS_KEY=your_secret

mlflow server \
    --host 0.0.0.0 \
    --port 5000 \
    --default-artifact-root s3://my-mlflow-bucket/artifacts \
    --backend-store-uri sqlite:////mlflow/mlflow.db
```

### Autenticación (Enterprise)

```bash
pip install mlflow[auth]

mlflow server \
    --host 0.0.0.0 \
    --port 5000 \
    --app-name basic-auth \
    --backend-store-uri sqlite:////mlflow/mlflow.db \
    --default-artifact-root /mlflow/artifacts
```

***

## Comparar ejecuciones en la UI

1. Abre la UI de MLflow en `http://<clore-host>:<port>`
2. Selecciona un experimento en el panel izquierdo
3. Marca las casillas junto a varias ejecuciones
4. Haz clic **Comparar** para ver métricas y parámetros lado a lado
5. Usa la **Pestaña de Gráficos** para comparación visual

***

## Solución de problemas

### No se puede conectar al servidor de seguimiento

```
mlflow.exceptions.MlflowException: La solicitud API falló con el código de estado 503
```

**Soluciones:**

* Comprueba que el puerto 5000 esté abierto y reenviado en Clore.ai
* Verifica que el servidor esté en ejecución: `ps aux | grep mlflow`
* Probar conectividad: `curl http://<clore-host>:<port>/health`

### Fallo en la subida de artefactos

**Solución:** Asegúrate de que el directorio de artefactos sea escribible:

```bash
chmod 777 /mlflow/artifacts
```

### Error SQLite Bloqueado (Escrituras Concurrentes)

**Solución:** Cambia a PostgreSQL para configuraciones multiusuario:

```bash
pip install psycopg2-binary
```

### El Registro de Modelos no aparece

**Solución:** Verifica que estés usando un `--backend-store-uri` que soporte el registro (SQLite o PostgreSQL — no solo una ruta local).

***

## Estimación de Costos

| Instancia     | Caso de uso                        | Precio estimado | Notas                   |
| ------------- | ---------------------------------- | --------------- | ----------------------- |
| CPU 4 núcleos | Solo servidor de seguimiento       | \~$0.05/hr      | Muy ligero              |
| RTX 3080      | Entrenamiento co-ubicado           | \~$0.10/hr      | Entrenamiento + MLflow  |
| RTX 4090      | Entrenamiento pesado + seguimiento | \~$0.35/hr      | Configuración más común |

{% hint style="info" %}
Ejecuta MLflow en una instancia CPU barata y apunta todos tus trabajos de entrenamiento en GPU hacia ella. De esta forma el servidor de seguimiento se ejecuta continuamente sin consumir caros créditos de GPU.
{% endhint %}

***

## Recursos Útiles

* [Documentación Oficial de MLflow](https://mlflow.org/docs/latest/index.html)
* [MLflow GitHub](https://github.com/mlflow/mlflow)
* [MLflow Docker Hub](https://github.com/mlflow/mlflow/pkgs/container/mlflow)
* [Guía del Registro de Modelos de MLflow](https://mlflow.org/docs/latest/model-registry.html)
* [Referencia de la API de Seguimiento de MLflow](https://mlflow.org/docs/latest/python_api/mlflow.html)

***

## Recomendaciones de GPU en Clore.ai

| Caso de uso                 | GPU recomendada | Coste estimado en Clore.ai |
| --------------------------- | --------------- | -------------------------- |
| Desarrollo/Pruebas          | RTX 3090 (24GB) | \~$0.12/gpu/hr             |
| Entrenamiento en Producción | RTX 4090 (24GB) | \~$0.70/gpu/hr             |
| Experimentos a Gran Escala  | A100 80GB       | \~$1.20/gpu/hr             |

> 💡 Todos los ejemplos en esta guía pueden desplegarse en [Clore.ai](https://clore.ai/marketplace) servidores GPU. Navega las GPUs disponibles y alquila por hora — sin compromisos, acceso root completo.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.clore.ai/guides/guides_v2-es/mlops-y-despliegue/mlflow.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
