t0 = time.time() para la época en el rango(EPOCHS): clave, sk = jax.random.split(key) perm = jax.random.permutation(sk, len(X_train)) X_s, Y_s = X_train[perm]Y_tren[perm]
epoch_loss = 0.0 para paso en rango (steps_per_epoch): xb = X_s[step*BATCH:(step+1)*BATCH]
yb = Y_s[step*BATCH:(step+1)*BATCH]
modelo, opt_state, pérdida = train_step(model, opt_state, xb, yb) epoch_loss += loss.item() val_loss = evaluar(modelo, X_val, Y_val).item() train_losses.append(epoch_loss / pasos_por_epoch) val_losses.append(val_loss) if (época + 1) % 5 == 0: print(f”Época {época+1:3d}/{EPOCHS} ” f”train_loss={train_losses[-1]:.5f} ” f”val_loss={val_losses[-1]:.5f}”) print(f”\nTiempo total de entrenamiento: {time.time()-t0:.1f}s”) print(“\n” + “=”*60) print(“SECCIÓN 7: Guardar y cargar pesos del modelo”) print(“=”*60) eqx.tree_serialise_leaves(“model_weights.eqx”, model) key, mk2 = jax.random.split(key) model_skeleton = ResNetMLP(1, 64, 1, n_blocks=4, key=mk2) model_loaded = eqx.tree_deserialise_leaves(“model_weights.eqx”, model_skeleton) diff = jnp.max(jnp.abs( jax.tree_util.tree_leaves(eqx.filter(model, eqx.is_array))[0]
– jax.tree_util.tree_leaves(eqx.filter(model_loaded, eqx.is_array))[0]
)) print(f”Diferencia de peso máxima después de la recarga: {diff:.2e} (debe ser 0.0)”) fig, axes = plt.subplots(1, 2, figsize=(12, 4)) axes[0].plot(train_losses, label=”Train MSE”, color=”#4C72B0″) ejes[0].plot(val_losses, label=”Val MSE”, color=”#DD8452″, linestyle=”–“) ejes[0].set_xlabel(“Época”) ejes[0].set_ylabel(“MSE”) ejes[0].set_title(“Curvas de entrenamiento”) ejes[0].legend() ejes[0].grid(True, alpha=0.3) x_plot = jnp.linspace(-1, 1, 300).reshape(-1, 1) y_true = jnp.sin(2 * jnp.pi * x_plot) y_pred = jax.vmap(model)(x_plot) ejes[1].dispersión(X_val[:100]valor_Y[:100]s=10, alfa=0.4, color=”gris”, etiqueta=”Datos”) ejes[1].plot(x_plot, y_true, color=”#4C72B0″, linewidth=2, label=”True f(x)”) ejes[1].plot(x_plot, y_pred, color=”#DD8452″, linewidth=2, linestyle=”–“, label=”Predicted”) ejes[1].set_xlabel(“x”) ejes[1].set_ylabel(“y”) ejes[1].set_title(“Ajuste de regresión sinusoidal”) ejes[1].legend() ejes[1].grid(True, alpha=0.3) plt.tight_layout() plt.savefig(“equinox_tutorial.png”, dpi=150) plt.show() print(“\n¡Listo! Gráfico guardado en equinox_tutorial.png”) print(“\n” + “=”*60) print(“BONIFICACIÓN: eqx.filter_jit + sugerencia de depuración de inferencia de formas”) print(“=”*60) jaxpr = jax.make_jaxpr(jax.vmap(model))(x_plot) n_eqns = len(jaxpr.jaxpr.eqns) print(f”ResNetMLP jaxpr compilado tiene {n_eqns} ecuaciones (ops) para entrada por lotes {x_plot.shape}”) BATCH = 128 EPOCHS = 30 pasos_por_epoch = len(X_train) // LOTES train_losses, val_losses = [], []
t0 = time.time() para la época en el rango(EPOCHS): clave, sk = jax.random.split(key) perm = jax.random.permutation(sk, len(X_train)) X_s, Y_s = X_train[perm]Y_tren[perm]
epoch_loss = 0.0 para paso en rango (steps_per_epoch): xb = X_s[step*BATCH:(step+1)*BATCH]
yb = Y_s[step*BATCH:(step+1)*BATCH]
modelo, opt_state, pérdida = train_step(model, opt_state, xb, yb) epoch_loss += loss.item() val_loss = evaluar(modelo, X_val, Y_val).item() train_losses.append(epoch_loss / pasos_por_epoch) val_losses.append(val_loss) if (época + 1) % 5 == 0: print(f”Época {época+1:3d}/{EPOCHS} ” f”train_loss={train_losses[-1]:.5f} ” f”val_loss={val_losses[-1]:.5f}”) print(f”\nTiempo total de entrenamiento: {time.time()-t0:.1f}s”) print(“\n” + “=”*60) print(“SECCIÓN 7: Guardar y cargar pesos del modelo”) print(“=”*60) eqx.tree_serialise_leaves(“model_weights.eqx”, model) key, mk2 = jax.random.split(key) model_skeleton = ResNetMLP(1, 64, 1, n_blocks=4, key=mk2) model_loaded = eqx.tree_deserialise_leaves(“model_weights.eqx”, model_skeleton) diff = jnp.max(jnp.abs( jax.tree_util.tree_leaves(eqx.filter(model, eqx.is_array))[0]
– jax.tree_util.tree_leaves(eqx.filter(model_loaded, eqx.is_array))[0]
)) print(f”Diferencia de peso máxima después de la recarga: {diff:.2e} (debe ser 0.0)”) fig, axes = plt.subplots(1, 2, figsize=(12, 4)) axes[0].plot(train_losses, label=”Train MSE”, color=”#4C72B0″) ejes[0].plot(val_losses, label=”Val MSE”, color=”#DD8452″, linestyle=”–“) ejes[0].set_xlabel(“Época”) ejes[0].set_ylabel(“MSE”) ejes[0].set_title(“Curvas de entrenamiento”) ejes[0].legend() ejes[0].grid(True, alpha=0.3) x_plot = jnp.linspace(-1, 1, 300).reshape(-1, 1) y_true = jnp.sin(2 * jnp.pi * x_plot) y_pred = jax.vmap(model)(x_plot) ejes[1].dispersión(X_val[:100]valor_Y[:100]s=10, alfa=0.4, color=”gris”, etiqueta=”Datos”) ejes[1].plot(x_plot, y_true, color=”#4C72B0″, linewidth=2, label=”True f(x)”) ejes[1].plot(x_plot, y_pred, color=”#DD8452″, linewidth=2, linestyle=”–“, label=”Predicted”) ejes[1].set_xlabel(“x”) ejes[1].set_ylabel(“y”) ejes[1].set_title(“Ajuste de regresión sinusoidal”) ejes[1].legend() ejes[1].grid(True, alpha=0.3) plt.tight_layout() plt.savefig(“equinox_tutorial.png”, dpi=150) plt.show() print(“\n¡Listo! Gráfico guardado en equinox_tutorial.png”) print(“\n” + “=”*60) print(“BONIFICACIÓN: eqx.filter_jit + sugerencia de depuración de inferencia de formas”) print(“=”*60) jaxpr = jax.make_jaxpr(jax.vmap(model))(x_plot) n_eqns = len(jaxpr.jaxpr.eqns) print(f”ResNetMLP jaxpr compilado tiene {n_eqns} ecuaciones (ops) para entrada por lotes {x_plot.shape}”)