Publicar modelo y Model Card
Browse files- README.md +34 -0
- cargar.py +31 -0
- exportar.py +36 -0
- model_ts.pt +3 -0
- requirements.txt +3 -0
README.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
language:
|
| 3 |
+
- es
|
| 4 |
+
library_name: pytorch
|
| 5 |
+
pipeline_tag: tabular-regression
|
| 6 |
+
tags:
|
| 7 |
+
- machine-learning
|
| 8 |
+
- regression
|
| 9 |
+
- linear-regression
|
| 10 |
+
- educational-example
|
| 11 |
+
- torchscript
|
| 12 |
+
license: mit
|
| 13 |
+
---
|
| 14 |
+
|
| 15 |
+
# PyTorch: exportar en formato TorchScript
|
| 16 |
+
|
| 17 |
+
Exporta el modelo entrenado en `pytorch-entrenamiento-evaluacion` al formato **TorchScript** (`model_ts.pt`) y lo vuelve a cargar para predecir.
|
| 18 |
+
|
| 19 |
+
## Cómo correrlo
|
| 20 |
+
|
| 21 |
+
```bash
|
| 22 |
+
python ../pytorch-entrenamiento-evaluacion/train.py # si todavía no está entrenado
|
| 23 |
+
python exportar.py
|
| 24 |
+
python cargar.py
|
| 25 |
+
```
|
| 26 |
+
|
| 27 |
+
## Qué guarda el formato
|
| 28 |
+
|
| 29 |
+
| | |
|
| 30 |
+
|---|---|
|
| 31 |
+
| **¿Qué guarda?** | los pesos y el código del `forward` |
|
| 32 |
+
| **¿Cómo se carga?** | `torch.jit.load`, sin la clase. |
|
| 33 |
+
| **¿Es seguro abrirlo si viene de un desconocido?** | Sí, no usa pickle. Está *deprecated*: PyTorch recomienda torch.export. |
|
| 34 |
+
| **¿Para qué caso?** | proyectos viejos o C++. Para algo nuevo, torch.export |
|
cargar.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Carga model_ts.pt y predice el precio de casas nuevas. No vuelve a entrenar.
|
| 2 |
+
|
| 3 |
+
Uso:
|
| 4 |
+
python cargar.py
|
| 5 |
+
"""
|
| 6 |
+
|
| 7 |
+
import json
|
| 8 |
+
from pathlib import Path
|
| 9 |
+
|
| 10 |
+
import numpy as np
|
| 11 |
+
import torch
|
| 12 |
+
|
| 13 |
+
CARPETA = Path(__file__).parent
|
| 14 |
+
ORIGEN = CARPETA.parent / "pytorch-entrenamiento-evaluacion"
|
| 15 |
+
ENTRADAS = ["m2", "balcon", "ascensor"]
|
| 16 |
+
|
| 17 |
+
# La normalización no viaja dentro del archivo: se lee de config.json
|
| 18 |
+
config = json.loads((ORIGEN / "config.json").read_text(encoding="utf-8"))
|
| 19 |
+
media = np.array(config["normalizacion"]["media"], dtype="float32")
|
| 20 |
+
desvio = np.array(config["normalizacion"]["desvio"], dtype="float32")
|
| 21 |
+
|
| 22 |
+
casas_nuevas = np.array([[50, 0, 0], [80, 1, 0], [110, 1, 1]], dtype="float32")
|
| 23 |
+
x = torch.tensor((casas_nuevas - media) / desvio)
|
| 24 |
+
|
| 25 |
+
# No hace falta la clase RegresionLineal: el código del forward viene en el archivo
|
| 26 |
+
modelo = torch.jit.load(CARPETA / "model_ts.pt")
|
| 27 |
+
with torch.no_grad():
|
| 28 |
+
precios = modelo(x).numpy()
|
| 29 |
+
|
| 30 |
+
for casa, precio in zip([[50, 0, 0], [80, 1, 0], [110, 1, 1]], np.ravel(precios)):
|
| 31 |
+
print(f"{dict(zip(ENTRADAS, casa))} -> {precio:.1f} miles de US$")
|
exportar.py
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Exporta el modelo de PyTorch en formato TorchScript: model_ts.pt.
|
| 2 |
+
|
| 3 |
+
No vuelve a entrenar: parte de ../pytorch-entrenamiento-evaluacion/model.safetensors
|
| 4 |
+
(correr antes ese train.py).
|
| 5 |
+
|
| 6 |
+
Uso:
|
| 7 |
+
python exportar.py
|
| 8 |
+
"""
|
| 9 |
+
|
| 10 |
+
import json
|
| 11 |
+
import sys
|
| 12 |
+
from pathlib import Path
|
| 13 |
+
|
| 14 |
+
import numpy as np
|
| 15 |
+
import torch
|
| 16 |
+
from safetensors.torch import load_file
|
| 17 |
+
|
| 18 |
+
CARPETA = Path(__file__).parent
|
| 19 |
+
ORIGEN = Path(__file__).parent.parent / "pytorch-entrenamiento-evaluacion"
|
| 20 |
+
sys.path.insert(0, str(ORIGEN))
|
| 21 |
+
from modelo import RegresionLineal # noqa: E402
|
| 22 |
+
|
| 23 |
+
# La normalización no viaja dentro del archivo: se lee de config.json
|
| 24 |
+
config = json.loads((ORIGEN / "config.json").read_text(encoding="utf-8"))
|
| 25 |
+
media = np.array(config["normalizacion"]["media"], dtype="float32")
|
| 26 |
+
desvio = np.array(config["normalizacion"]["desvio"], dtype="float32")
|
| 27 |
+
|
| 28 |
+
modelo = RegresionLineal(n_entradas=len(config["entradas"]))
|
| 29 |
+
modelo.load_state_dict(load_file(ORIGEN / "model.safetensors"))
|
| 30 |
+
modelo.eval()
|
| 31 |
+
|
| 32 |
+
# trace pasa un ejemplo por el modelo y graba las operaciones que se ejecutan.
|
| 33 |
+
# En PyTorch nuevo muestra un aviso de deprecated: recomiendan torch.export.
|
| 34 |
+
ejemplo = torch.zeros(1, 3)
|
| 35 |
+
torch.jit.trace(modelo, ejemplo).save(CARPETA / "model_ts.pt")
|
| 36 |
+
print("Modelo guardado en model_ts.pt")
|
model_ts.pt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:d0ecc8e75969f8dcc1aab653945d52155838cce4e2e81af062ef986e746bbbec
|
| 3 |
+
size 4258
|
requirements.txt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
torch>=2.1
|
| 2 |
+
safetensors
|
| 3 |
+
numpy
|