Agregar guia de peso y estimar_foto
Browse files- entrenamiento/GUIA_PESO.md +299 -0
- entrenamiento/estimar_foto.py +31 -0
entrenamiento/GUIA_PESO.md
ADDED
|
@@ -0,0 +1,299 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Guía del modelo de peso (Revalora IA)
|
| 2 |
+
|
| 3 |
+
Última actualización: 2026-11-10
|
| 4 |
+
|
| 5 |
+
Léela completa antes de entrenar nada. Resume qué se hizo, con qué datos, qué resultados dio y qué falta.
|
| 6 |
+
|
| 7 |
+
---
|
| 8 |
+
|
| 9 |
+
## 1. Objetivo
|
| 10 |
+
|
| 11 |
+
Estimar el **peso en gramos** de un objeto. El modelo de peso (LightGBM) recibe **números**, no fotos:
|
| 12 |
+
material, largo, ancho, espesor y número de piezas. El flujo final que se busca es:
|
| 13 |
+
|
| 14 |
+
foto → material + piezas + medidas → LightGBM → peso
|
| 15 |
+
|
| 16 |
+
Hoy solo está terminada la última parte (características → peso). Ver sección 10.
|
| 17 |
+
|
| 18 |
+
---
|
| 19 |
+
|
| 20 |
+
## 2. Entorno
|
| 21 |
+
|
| 22 |
+
- Windows, PowerShell, VS Code, `uv`.
|
| 23 |
+
- Proyecto: `EagleDev-Innovacion\revalora-ia-service`. Todos los comandos se corren desde esa carpeta.
|
| 24 |
+
- Entorno virtual: `.venv` (activar con `.venv\Scripts\Activate.ps1`).
|
| 25 |
+
- Modelos y datos compartidos: repo de Hugging Face `EagleDev-Innovation/Modelos-EagleDev-Innovation`.
|
| 26 |
+
- Para subir necesitas ser miembro de la organización `EagleDev-Innovation` y un token con permiso **Write**:
|
| 27 |
+
|
| 28 |
+
```powershell
|
| 29 |
+
uv pip install huggingface_hub
|
| 30 |
+
hf auth login
|
| 31 |
+
hf auth whoami
|
| 32 |
+
```
|
| 33 |
+
|
| 34 |
+
---
|
| 35 |
+
|
| 36 |
+
## 3. Estado actual
|
| 37 |
+
|
| 38 |
+
| Pieza | Estado |
|
| 39 |
+
|---|---|
|
| 40 |
+
| LightGBM de peso (`modelos_entrenados/peso/lgbm_peso.joblib`) | Entrenado y subido a Hugging Face |
|
| 41 |
+
| Datos propios de peso | Solo 12 filas, todas barras de acero de 12 mm (`metal`) |
|
| 42 |
+
| Dataset externo EMMa (Stanford) | Descargado (6.7 GB), convertido a `emma_mat.csv` |
|
| 43 |
+
| Búsqueda por similitud con CLIP (foto → productos parecidos) | Scripts listos, índice **sin terminar** (muy lento en CPU) |
|
| 44 |
+
| Foto → medidas en cm | **No existe** |
|
| 45 |
+
| Integración en el backend | Pendiente |
|
| 46 |
+
| Modelos `conteo` y `material_estado` | Ya existen en el repo de Hugging Face (no se documentan en esta guía) |
|
| 47 |
+
|
| 48 |
+
---
|
| 49 |
+
|
| 50 |
+
## 4. Archivos (carpeta `entrenamiento\`)
|
| 51 |
+
|
| 52 |
+
| Archivo | Para qué sirve |
|
| 53 |
+
|---|---|
|
| 54 |
+
| `hf_sync.py` | `bajar` / `subir "mensaje"` de la carpeta `modelos_entrenados` |
|
| 55 |
+
| `hf_sync_datos.py` | `bajar` / `subir "mensaje"` de scripts y CSV (ver sección 11) |
|
| 56 |
+
| `importar_emma_mat.py` | Lee el `.fdd` de EMMa y genera `datos/externos/emma_mat.csv` |
|
| 57 |
+
| `entrenar_peso.py` | Entrena y valida el LightGBM de peso |
|
| 58 |
+
| `probar_peso.py` | Predice peso con valores a mano |
|
| 59 |
+
| `probar_foto.py` | Igual que el anterior, pero recibe la ruta de una foto (solo comprueba que exista, el peso sale de las medidas que se escriben) |
|
| 60 |
+
| `indexar_emma.py` | Crea el índice CLIP de títulos de EMMa |
|
| 61 |
+
| `estimar_foto.py` | Busca en el índice los productos parecidos a una foto y estima el peso |
|
| 62 |
+
| `ver_emma.py`, `splits_emma.py` | Scripts de exploración del `.fdd` (se pueden ignorar) |
|
| 63 |
+
| `importar_emma.py`, `limpiar_emma.py` | Versión anterior (sin material ni espesor). **Reemplazados** por `importar_emma_mat.py` |
|
| 64 |
+
| `importar_externos.py` | Script anterior de datos externos. Ya no lo usa `entrenar_peso.py` |
|
| 65 |
+
|
| 66 |
+
Otros archivos de la carpeta (`afinar_completo.py`, `buscar_roboflow.py`, `colab_entrenamiento.ipynb`, `entrenar.py`, `evaluar_conteo.py`, etc.) son de los modelos de conteo y material, y no se tocaron en este trabajo.
|
| 67 |
+
|
| 68 |
+
---
|
| 69 |
+
|
| 70 |
+
## 5. Datos
|
| 71 |
+
|
| 72 |
+
### 5.1 Datos propios: `datos/peso/caracteristicas.csv`
|
| 73 |
+
|
| 74 |
+
Columnas: `foto, sesion, tipo_objeto, material, n_piezas, area_cm2_total, largo_cm_medio, ancho_cm_medio, largo_cm_max, espesor_cm, peso_real_g`.
|
| 75 |
+
|
| 76 |
+
- 12 filas, todas barras de acero de 12 mm (`material = metal`). Ejemplo: 1 barra = 888 g, 2 barras = 1780 g, 3 barras = 2650 g.
|
| 77 |
+
- `area_cm2_total` es el área **de todas las piezas juntas** (120, 240, 360...). El entrenamiento la divide entre `n_piezas`.
|
| 78 |
+
- `largo_cm_max` es ~1 % mayor que `largo_cm_medio` (101 contra 100).
|
| 79 |
+
- `espesor_cm` se agregó a mano (1.2).
|
| 80 |
+
- Esta es la parte débil del proyecto: con esto no se puede validar nada fuera del acero.
|
| 81 |
+
|
| 82 |
+
### 5.2 Dataset externo: EMMa v1.1 (Stanford)
|
| 83 |
+
|
| 84 |
+
- Archivo: `datos/externos/EMMa_v1.1.fdd` (6,692,678,168 bytes ≈ 6.7 GB), con título, descripción, atributos (masa, dimensiones, categoría, materiales como vector).
|
| 85 |
+
- Descarga (reanuda si se corta):
|
| 86 |
+
|
| 87 |
+
```powershell
|
| 88 |
+
mkdir datos\externos -Force
|
| 89 |
+
curl.exe -L -C - -o datos\externos\EMMa_v1.1.fdd https://downloads.cs.stanford.edu/downloads/emma/EMMa_v1.1.fdd
|
| 90 |
+
```
|
| 91 |
+
|
| 92 |
+
- **No** se descargó el archivo de imágenes (185 GB), no hace falta.
|
| 93 |
+
- **No** subir el `.fdd` a Hugging Face: cada quien lo descarga de Stanford.
|
| 94 |
+
|
| 95 |
+
### 5.3 Cómo se lee el `.fdd` (importante)
|
| 96 |
+
|
| 97 |
+
El paquete `freeze-dried-data` 2.6.4 **no sirve** para este archivo (`RFDD` da `Split not found` y no existe `FDD`). Se lee a mano:
|
| 98 |
+
|
| 99 |
+
- Los últimos 8 bytes son el tamaño del índice.
|
| 100 |
+
- El índice es un pickle `asin → (inicio, largo)`.
|
| 101 |
+
- Cada registro es un pickle (a veces comprimido con zlib) con: `materials, category, price, mass, ratings, dimensions, quantity, custom, image_hashes, title, features, description`.
|
| 102 |
+
- 2,883,694 registros.
|
| 103 |
+
- Unidades verificadas con medianas razonables: **masa en kg, dimensiones en pulgadas**. Son 3 valores por objeto; se ordenan de mayor a menor (largo, ancho, espesor).
|
| 104 |
+
|
| 105 |
+
### 5.4 `datos/externos/emma_mat.csv` (lo que se usa para entrenar)
|
| 106 |
+
|
| 107 |
+
Lo genera `importar_emma_mat.py` con estos filtros:
|
| 108 |
+
|
| 109 |
+
- Un solo producto (`quantity == 1`) con una sola medida de dimensiones.
|
| 110 |
+
- Masa entre 5 y 30,000 g. Largo 1–150 cm, ancho 0.5–150 cm, espesor ≥ 0.1 cm.
|
| 111 |
+
- **Material** asignado por palabras clave del título y las características (en inglés). Solo se conservan los productos que coinciden con **un único** material: `metal, plastico, madera, vidrio, ceramica, carton, tela`.
|
| 112 |
+
- Columnas: `material, n_piezas, area_cm2_total, largo_cm_medio, ancho_cm_medio, largo_cm_max, espesor_cm, peso_real_g`.
|
| 113 |
+
- Quedan cientos de miles de filas (en el entrenamiento se muestrean 300,000).
|
| 114 |
+
|
| 115 |
+
Limitación: el material por palabras clave es aproximado, y EMMa tiene muchos productos **huecos** (envases, cajas), por eso el modelo tiende a subestimar objetos macizos.
|
| 116 |
+
|
| 117 |
+
---
|
| 118 |
+
|
| 119 |
+
## 6. Modelo de peso
|
| 120 |
+
|
| 121 |
+
Archivo: `entrenar_peso.py`. Configuración actual:
|
| 122 |
+
|
| 123 |
+
- **Features:** `area_pieza` (área total ÷ n_piezas), `largo_cm_medio`, `ancho_cm_medio`, `largo_cm_max`, `relacion` (largo ÷ ancho), `espesor_cm`, `volumen_cm3` (area_pieza × espesor) y `material` en uno-caliente.
|
| 124 |
+
- **Objetivo:** peso **por pieza** en escala logarítmica (`TransformedTargetRegressor` con `log1p` / `expm1`). Al predecir sale en gramos por pieza; se multiplica por `n_piezas`.
|
| 125 |
+
- **LightGBM:** 600 árboles, `learning_rate=0.05`, `num_leaves=63`, `min_child_samples=30`, `subsample=0.8`.
|
| 126 |
+
- **Pesos de muestra:** datos propios = 20, EMMa = 1 (`W_PROPIO = 20`).
|
| 127 |
+
- **Muestreo:** `MAX_EXT = 300000` filas de EMMa.
|
| 128 |
+
- Se guarda en `modelos_entrenados/peso/lgbm_peso.joblib` con las claves `modelo`, `columnas` y `cat`.
|
| 129 |
+
|
| 130 |
+
### Validación
|
| 131 |
+
|
| 132 |
+
Se hacen dos: (1) 20 % de EMMa reservado, (2) tus datos propios por sesión (GroupKFold), comparando contra un modelo lineal solo con datos propios.
|
| 133 |
+
|
| 134 |
+
### Resultados (2026-11-10)
|
| 135 |
+
|
| 136 |
+
| Prueba | Resultado |
|
| 137 |
+
|---|---|
|
| 138 |
+
| EMMa reservado | MAE 1263 g, error mediano **47.9 %** |
|
| 139 |
+
| Propio, lineal | MAE 8.5 g (0.4 %) |
|
| 140 |
+
| Propio, LightGBM | MAE **11.5 g** (0.5 %) |
|
| 141 |
+
|
| 142 |
+
### Decisiones y por qué
|
| 143 |
+
|
| 144 |
+
1. **Se agregó el espesor.** Sin él (solo largo y ancho) el error mediano en EMMa era 56 % y en las barras 111.9 g de MAE.
|
| 145 |
+
2. **Se quitó `tipo_objeto`** de las features: los tipos propios no existen en EMMa.
|
| 146 |
+
3. **`min_child_samples=30` y no 5.** Con 5 el modelo memoriza las 12 filas propias y la validación empeora (67.7 g).
|
| 147 |
+
4. **Peso en logaritmo**, porque los pesos van de 5 g a 30 kg.
|
| 148 |
+
5. El error de ~48 % en EMMa es el techo con estas features: dos productos del mismo tamaño y material pueden pesar muy distinto (macizo contra hueco).
|
| 149 |
+
|
| 150 |
+
---
|
| 151 |
+
|
| 152 |
+
## 7. Cómo reproducir
|
| 153 |
+
|
| 154 |
+
Desde `revalora-ia-service` con el venv activo:
|
| 155 |
+
|
| 156 |
+
```powershell
|
| 157 |
+
# 1. Datos (descarga 1 vez, ~1 hora)
|
| 158 |
+
mkdir datos\externos -Force
|
| 159 |
+
curl.exe -L -C - -o datos\externos\EMMa_v1.1.fdd https://downloads.cs.stanford.edu/downloads/emma/EMMa_v1.1.fdd
|
| 160 |
+
|
| 161 |
+
# 2. Convertir a CSV (~3 min)
|
| 162 |
+
python entrenamiento\importar_emma_mat.py
|
| 163 |
+
|
| 164 |
+
# 3. Entrenar y validar
|
| 165 |
+
python entrenamiento\entrenar_peso.py
|
| 166 |
+
|
| 167 |
+
# 4. Probar
|
| 168 |
+
python entrenamiento\probar_peso.py
|
| 169 |
+
python entrenamiento\probar_peso.py plastico 20 10 5
|
| 170 |
+
python entrenamiento\probar_peso.py madera 25 10 2 4 # 4 piezas
|
| 171 |
+
|
| 172 |
+
# 5. Subir (solo si los resultados no empeoraron)
|
| 173 |
+
python entrenamiento\hf_sync.py subir "descripción del cambio"
|
| 174 |
+
```
|
| 175 |
+
|
| 176 |
+
Si ya están `emma_mat.csv` y `caracteristicas.csv` en Hugging Face, se saltan los pasos 1 y 2 con `python entrenamiento\hf_sync_datos.py bajar`.
|
| 177 |
+
|
| 178 |
+
Orden de `probar_peso.py`: material, largo, ancho, espesor (cm) y, opcional, número de piezas. Materiales válidos: `metal`, `plastico`, `madera`, `vidrio`, `ceramica`, `carton`, `tela`. En PowerShell no escribas los `<...>` de los ejemplos: son marcadores.
|
| 179 |
+
|
| 180 |
+
---
|
| 181 |
+
|
| 182 |
+
## 8. Pruebas hechas
|
| 183 |
+
|
| 184 |
+
| Objeto | Predicho | Real |
|
| 185 |
+
|---|---|---|
|
| 186 |
+
| Barra de acero 100×1.2×1.2 cm | 873 g | 888 g |
|
| 187 |
+
| 3 barras de acero | 2619 g | 2650 g |
|
| 188 |
+
| Madera 30×20×2 cm | ~800 g | sin pesar |
|
| 189 |
+
| Plástico 20×10×5 cm | ~240 g | sin pesar |
|
| 190 |
+
| Cartón 40×30×20 cm | ~3000 g | sin pesar |
|
| 191 |
+
| Vidrio 20×8×8 cm | ~690 g | sin pesar |
|
| 192 |
+
|
| 193 |
+
Solo el acero está validado con peso real. Pendiente: probar un bidón de agua de ~20 L vacío (usar plástico, ~50 × 27 × 27 cm, y pesarlo vacío; el modelo predice el objeto, no el contenido) y una hoja de papel (A4 ≈ 5 g, probablemente fuera de lo que vio el modelo).
|
| 194 |
+
|
| 195 |
+
---
|
| 196 |
+
|
| 197 |
+
## 9. Búsqueda por similitud con CLIP
|
| 198 |
+
|
| 199 |
+
Idea: dada una foto, buscar los productos de EMMa más parecidos (CLIP compara la foto con los **títulos**) y estimar el peso con los vecinos.
|
| 200 |
+
|
| 201 |
+
- `indexar_emma.py` toma 150,000 productos válidos de EMMa y guarda `datos/externos/emma_clip.npy` y `emma_clip.csv`.
|
| 202 |
+
- `estimar_foto.py` recibe la ruta de una foto (y opcionalmente una pista en inglés, ej. `plastic water jug`), muestra los 15 vecinos más parecidos y da la mediana ponderada de su peso.
|
| 203 |
+
- **Estado:** el 2026-11-10 se probó en CPU: ~19 s por lote, ~3 horas en total, sin terminar. En una GPU de Colab tarda unos minutos. Hay que correrlo en Colab (ver abajo) o bajar `N` en el script.
|
| 204 |
+
- Todavía no se evaluó si las coincidencias son buenas. Revisar siempre la lista de vecinos impresa: si no son del mismo tipo de objeto, el estimado no sirve.
|
| 205 |
+
|
| 206 |
+
Uso en Colab (GPU):
|
| 207 |
+
|
| 208 |
+
```python
|
| 209 |
+
!pip install -q sentence-transformers pillow huggingface_hub pandas lightgbm scikit-learn joblib
|
| 210 |
+
from huggingface_hub import login
|
| 211 |
+
from google.colab import userdata
|
| 212 |
+
login(userdata.get("HF_TOKEN"))
|
| 213 |
+
```
|
| 214 |
+
Luego descargar los scripts (`hf_sync_datos.py bajar`), bajar el `.fdd` con `!curl -L -C - -o datos/externos/EMMa_v1.1.fdd <URL>`, correr `!python entrenamiento/indexar_emma.py` y subir con `hf_sync_datos.py subir`.
|
| 215 |
+
|
| 216 |
+
---
|
| 217 |
+
|
| 218 |
+
## 10. Qué falta (por prioridad)
|
| 219 |
+
|
| 220 |
+
1. **Más datos propios variados.** Es lo que más mejora el modelo. Pesar 5–10 objetos de cada material (plástico, madera, cartón, vidrio, cerámica, tela, metal distinto al acero), medir largo, ancho y espesor, y agregarlos a `datos/peso/caracteristicas.csv` con `espesor_cm` y una `sesion` distinta por lote. Después reentrenar. Con esto la validación `[propio]` empieza a significar algo.
|
| 221 |
+
2. **Foto → medidas en cm.** Una foto no trae escala. Opciones: objeto de referencia en la foto (hoja A4, tarjeta de 8.5×5.4 cm) para calcular cm por píxel, o que el usuario escriba las medidas. Decidir cuál.
|
| 222 |
+
3. **Espesor.** También hay que pedirlo o asignarlo por tipo de objeto (hoja de papel ≈ 0.01 cm).
|
| 223 |
+
4. **Conectar** `material_estado` (material) y `conteo` (piezas) con el LightGBM en un endpoint (`POST /peso` que reciba la imagen).
|
| 224 |
+
5. **Terminar y evaluar el índice CLIP** y decidir si se combina con el LightGBM (el LightGBM con medidas reales debería ser más preciso).
|
| 225 |
+
6. **Papel y objetos muy delgados:** EMMa se filtró con espesor ≥ 1 mm, así que el modelo no vio hojas sueltas. Necesitan datos propios.
|
| 226 |
+
7. **Objetos de obra** (barras, tablones, cemento): EMMa son productos de Amazon, con pocas coincidencias buenas.
|
| 227 |
+
|
| 228 |
+
---
|
| 229 |
+
|
| 230 |
+
## 11. Integración con el backend
|
| 231 |
+
|
| 232 |
+
Para predecir, el backend debe armar exactamente estas columnas (la lista oficial está en la clave `columnas` del `.joblib`):
|
| 233 |
+
|
| 234 |
+
- `area_pieza` = área total ÷ n_piezas
|
| 235 |
+
- `largo_cm_medio`, `ancho_cm_medio`
|
| 236 |
+
- `largo_cm_max` = longitud máxima medida de la pieza (en las barras es ~1.01 × el largo medio; no copiar el largo medio, las predicciones salen más bajas)
|
| 237 |
+
- `relacion` = largo ÷ ancho
|
| 238 |
+
- `espesor_cm`
|
| 239 |
+
- `volumen_cm3` = area_pieza × espesor
|
| 240 |
+
- `material_carton, material_ceramica, material_madera, material_metal, material_plastico, material_tela, material_vidrio` (uno en 1, el resto en 0)
|
| 241 |
+
|
| 242 |
+
La predicción sale en **gramos por pieza**; hay que multiplicar por `n_piezas`. Ver `probar_peso.py` como ejemplo exacto.
|
| 243 |
+
|
| 244 |
+
---
|
| 245 |
+
|
| 246 |
+
## 12. Compartir trabajo (Hugging Face)
|
| 247 |
+
|
| 248 |
+
`hf_sync.py` maneja los modelos (`modelos_entrenados/`). `hf_sync_datos.py` maneja scripts y CSV:
|
| 249 |
+
|
| 250 |
+
```python
|
| 251 |
+
import sys
|
| 252 |
+
from huggingface_hub import snapshot_download, upload_folder
|
| 253 |
+
|
| 254 |
+
REPO = "EagleDev-Innovation/Modelos-EagleDev-Innovation"
|
| 255 |
+
PATRONES = [
|
| 256 |
+
"entrenamiento/*.py", "entrenamiento/*.md", "entrenamiento/*.ipynb",
|
| 257 |
+
"datos/peso/*.csv",
|
| 258 |
+
"datos/externos/emma_mat.csv",
|
| 259 |
+
"datos/externos/emma_clip.*",
|
| 260 |
+
]
|
| 261 |
+
|
| 262 |
+
def bajar():
|
| 263 |
+
snapshot_download(repo_id=REPO, repo_type="model",
|
| 264 |
+
allow_patterns=PATRONES, local_dir=".")
|
| 265 |
+
print("Código y datos descargados")
|
| 266 |
+
|
| 267 |
+
def subir(mensaje):
|
| 268 |
+
upload_folder(repo_id=REPO, repo_type="model", folder_path=".",
|
| 269 |
+
allow_patterns=PATRONES,
|
| 270 |
+
ignore_patterns=[".venv/**", "**/__pycache__/**"],
|
| 271 |
+
commit_message=mensaje)
|
| 272 |
+
print("Código y datos subidos")
|
| 273 |
+
|
| 274 |
+
if __name__ == "__main__":
|
| 275 |
+
if sys.argv[1] == "bajar":
|
| 276 |
+
bajar()
|
| 277 |
+
elif sys.argv[1] == "subir":
|
| 278 |
+
subir(sys.argv[2] if len(sys.argv) > 2 else "Actualizar código y datos")
|
| 279 |
+
```
|
| 280 |
+
|
| 281 |
+
Reglas de equipo:
|
| 282 |
+
|
| 283 |
+
- **`bajar` sobrescribe archivos locales.** Antes de bajar, sube o guarda lo tuyo; si no, pierdes cambios.
|
| 284 |
+
- Hugging Face guarda historial: si alguien sube algo peor, se puede volver al commit anterior desde la pestaña *Files and versions*.
|
| 285 |
+
- Suban un modelo solo si `[propio]` y `[EMMA holdout]` no empeoraron. Pongan el resultado en el mensaje del commit.
|
| 286 |
+
- Avísense quién entrena para no pisarse en la misma carpeta.
|
| 287 |
+
- No suban tokens, ni el `.fdd`, ni el `.venv`.
|
| 288 |
+
|
| 289 |
+
---
|
| 290 |
+
|
| 291 |
+
## 13. Errores que ya pasaron
|
| 292 |
+
|
| 293 |
+
- `RFDD` con `Split not found` o `cannot import name 'FDD'`: leer el `.fdd` a mano (sección 5.3).
|
| 294 |
+
- En PowerShell, `<material>` da error: no escribir los `<>`.
|
| 295 |
+
- `.Replace(...)` sobre un script **no avisa si no encontró el texto**: el archivo queda igual. Verificar con `Select-String -Path archivo -Pattern 'texto'`.
|
| 296 |
+
- `largo_cm_max` en la prueba debe ser ~1.01 × el largo (como en los datos propios), o las barras salen ~30 % más bajas.
|
| 297 |
+
- `hf_sync.py subir` puede imprimir "No files have been modified" aunque haya subido: comprobar la fecha del archivo en Hugging Face.
|
| 298 |
+
- Los avisos de symlinks de Hugging Face en Windows son inofensivos.
|
| 299 |
+
- CLIP en CPU es muy lento (ver sección 9).
|
entrenamiento/estimar_foto.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import sys
|
| 2 |
+
import numpy as np
|
| 3 |
+
import pandas as pd
|
| 4 |
+
from PIL import Image
|
| 5 |
+
from sentence_transformers import SentenceTransformer
|
| 6 |
+
|
| 7 |
+
K = 15
|
| 8 |
+
emb = np.load("datos/externos/emma_clip.npy").astype("float32")
|
| 9 |
+
df = pd.read_csv("datos/externos/emma_clip.csv")
|
| 10 |
+
model = SentenceTransformer("clip-ViT-B-32")
|
| 11 |
+
|
| 12 |
+
img = Image.open(sys.argv[1]).convert("RGB")
|
| 13 |
+
q = model.encode(img, normalize_embeddings=True)
|
| 14 |
+
if len(sys.argv) > 2: # pista opcional en inglés, ej: "plastic water jug"
|
| 15 |
+
t = model.encode(" ".join(sys.argv[2:]), normalize_embeddings=True)
|
| 16 |
+
q = q + t
|
| 17 |
+
q = q / np.linalg.norm(q)
|
| 18 |
+
|
| 19 |
+
sim = emb @ q
|
| 20 |
+
top = np.argsort(-sim)[:K]
|
| 21 |
+
sel = df.iloc[top].copy()
|
| 22 |
+
sel["sim"] = sim[top]
|
| 23 |
+
|
| 24 |
+
print("\nCoincidencias más parecidas:")
|
| 25 |
+
for _, r in sel.iterrows():
|
| 26 |
+
print(f"{r.sim:.3f} | {r.peso_g:7.0f} g | {str(r.dims_cm):22s} | {r.title[:60]}")
|
| 27 |
+
|
| 28 |
+
o = np.argsort(sel.peso_g.to_numpy())
|
| 29 |
+
p, w = sel.peso_g.to_numpy()[o], sel.sim.to_numpy()[o]
|
| 30 |
+
mediana = p[np.searchsorted(np.cumsum(w) / w.sum(), 0.5)]
|
| 31 |
+
print(f"\nPeso estimado: {mediana:.0f} g (rango típico {np.percentile(p, 25):.0f} - {np.percentile(p, 75):.0f} g)")
|