O que é MLOps e por que importa
MLOps é a disciplina de levar modelos de machine learning para produção com o mesmo rigor que engenharia de software aplica a aplicações web. No notebook, tudo funciona: você carrega um CSV, treina um modelo, olha o AUC e segue em frente. Em produção, surgem perguntas que o notebook não responde: qual versão dos dados treinou esse modelo? Quais hiperparâmetros foram usados? Como reproduzir o resultado daqui a seis meses?
Sem versionamento e rastreabilidade, cada retreino vira uma aposta. O modelo novo pode ter piorado e ninguém percebe até o negócio reclamar. MLOps resolve isso com três pilares: versionar dados, registrar experimentos e promover artefatos de forma controlada.
Duas ferramentas cobrem a maior parte do caminho em projetos Python: DVC para dados e pipelines, MLflow para tracking e model registry. Este post mostra como usá-las juntas.
O ciclo MLOps em quatro etapas
Todo projeto MLOps maduro passa por um ciclo repetível:
- Dados versionados — snapshot rastreável do dataset de treino
- Treino reprodutível — script com parâmetros fixos e seed
- Tracking de experimentos — métricas, parâmetros e artefatos logados
- Deploy do artefato — modelo aprovado promovido para produção
DVC versiona datasets e features. Cada commit de dados fica rastreável e reprodutível — você sabe exatamente com qual snapshot o modelo foi treinado.
Cada etapa produz um artefato que alimenta a próxima. Quebrar a cadeia em qualquer ponto — dados sem versão, treino manual, métricas em planilha — é o que transforma MLOps em buzzword.
Versionando dados com DVC
DVC (Data Version Control) trata datasets como Git trata código. Em vez de commitar CSVs de 2 GB no repositório, você commita um arquivo .dvc que aponta para o storage remoto (S3, GCS, local).
# Inicializar DVC no projeto
dvc init
dvc remote add -d storage s3://meu-bucket/dvc-store
# Versionar um dataset
dvc add data/train.parquet
git add data/train.parquet.dvc data/.gitignore
git commit -m "add training data v1"
dvc push
Para reproduzir o ambiente de treino em outra máquina ou no CI:
git checkout abc1234 # commit com data v1
dvc pull # baixa o dataset correspondente
python src/train.py # treina com os mesmos dados
O arquivo dvc.yaml define o pipeline como stages encadeados:
stages:
prepare:
cmd: python src/prepare.py
deps:
- src/prepare.py
- data/raw/transactions.csv
outs:
- data/processed/train.parquet
train:
cmd: python src/train.py
deps:
- src/train.py
- data/processed/train.parquet
outs:
- models/model.pkl
metrics:
- metrics.json
dvc repro executa apenas os stages que mudaram — igual a um Makefile para ML.
Registrando experimentos com MLflow
MLflow Tracking loga tudo que importa de cada execução de treino: parâmetros, métricas, artefatos e tags.
import mlflow
import mlflow.sklearn
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import roc_auc_score
mlflow.set_tracking_uri("http://localhost:5000")
mlflow.set_experiment("credit-score")
with mlflow.start_run(run_name="rf-baseline-v2"):
params = {"n_estimators": 200, "max_depth": 8, "class_weight": "balanced"}
model = RandomForestClassifier(**params, random_state=42)
model.fit(X_train, y_train)
auc = roc_auc_score(y_test, model.predict_proba(X_test)[:, 1])
mlflow.log_params(params)
mlflow.log_metric("auc_roc", auc)
mlflow.log_metric("auc_pr", average_precision_score(y_test, model.predict_proba(X_test)[:, 1]))
mlflow.sklearn.log_model(model, "model", registered_model_name="credit-score")
A UI do MLflow (mlflow ui) permite comparar runs lado a lado — essencial para decidir qual modelo promover.
O Model Registry adiciona estágios: None → Staging → Production. Promover um modelo é uma ação auditável, não um cp model.pkl /prod/.
Integrando DVC e MLflow
O fluxo ideal combina as duas ferramentas:
import subprocess
import mlflow
# Garantir dados versionados antes do treino
subprocess.run(["dvc", "repro", "train"], check=True)
with mlflow.start_run():
mlflow.log_param("data_version", subprocess.check_output(
["git", "rev-parse", "HEAD"]
).decode().strip())
# ... treino e log de métricas
Logar o hash do commit Git e a versão DVC como parâmetros do MLflow cria rastreabilidade completa: para qualquer run, você sabe exatamente qual código e qual dataset foram usados.
Exemplo prático: estrutura de projeto
mlops-credit/
├── data/
│ ├── raw/ # gitignored, rastreado por DVC
│ └── processed/
├── models/ # gitignored, output do pipeline
├── src/
│ ├── prepare.py
│ └── train.py
├── dvc.yaml
├── dvc.lock
├── metrics.json
├── requirements.txt
└── .github/workflows/ # CI (próximo post)
Regras simples que evitam dor:
- Nunca commitar datasets brutos no Git — use DVC
- Nunca treinar sem logar no MLflow — mesmo em experimentos descartáveis
metrics.jsonversionado pelo DVC permite comparar métricas entre commits
Além do básico: pontos de atenção
Armadilhas comuns ao adotar MLOps:
- DVC sem remote — versionar localmente não ajuda se o disco morre; configure S3 ou equivalente
- MLflow sem servidor —
mlflow uilocal funciona para um dev; em time, use MLflow server ou Databricks - Logar tudo menos o preprocessador — o artefato de produção é o pipeline completo, não só o classificador
- Métricas offline sem validação temporal — em crédito, split por data é obrigatório
- Ignorar
dvc.lock— commitar o lock garante reprodutibilidade exata do pipeline
Boas práticas:
- Taggear releases no Git quando promover modelo para produção
- Automatizar
dvc repro+ treino no CI (coberto no post de GitHub Actions) - Documentar no README como reproduzir qualquer experimento em três comandos
Conclusão
MLOps começa com versionamento: dados via DVC, experimentos via MLflow, código via Git. O ciclo Dados → Treino → Tracking → Deploy transforma cada retreino de aposta em processo auditável.
O próximo passo natural é automatizar esse ciclo no CI/CD — o tema do post sobre GitHub Actions para pipelines de ML.