Close Menu
    Facebook X (Twitter) Instagram
    Articles Stock
    • Home
    • Technology
    • AI
    • Pages
      • About ArticlesStock — AI & Technology Journalist
      • Contact us
      • Disclaimer For Articles Stock
      • Privacy Policy
      • Terms and Conditions
    Facebook X (Twitter) Instagram
    Articles Stock
    AI

    A Detailed Implementation on Equinox with JAX Native Modules, Filtered Transforms, Stateful Layers, and Finish-to-Finish Coaching Workflows

    Naveed AhmadBy Naveed Ahmad23/04/2026Updated:23/04/2026No Comments3 Mins Read
    blog 63


    BATCH  = 128
    EPOCHS = 30
    steps_per_epoch = len(X_train) // BATCH
    train_losses, val_losses = [], []
    
    
    t0 = time.time()
    for epoch in vary(EPOCHS):
       key, sk = jax.random.break up(key)
       perm = jax.random.permutation(sk, len(X_train))
       X_s, Y_s = X_train[perm], Y_train[perm]
    
    
       epoch_loss = 0.0
       for step in vary(steps_per_epoch):
           xb = X_s[step*BATCH:(step+1)*BATCH]
           yb = Y_s[step*BATCH:(step+1)*BATCH]
           mannequin, opt_state, loss = train_step(mannequin, opt_state, xb, yb)
           epoch_loss += loss.merchandise()
    
    
       val_loss = consider(mannequin, X_val, Y_val).merchandise()
       train_losses.append(epoch_loss / steps_per_epoch)
       val_losses.append(val_loss)
    
    
       if (epoch + 1) % 5 == 0:
           print(f"Epoch {epoch+1:3d}/{EPOCHS}  "
                 f"train_loss={train_losses[-1]:.5f}  "
                 f"val_loss={val_losses[-1]:.5f}")
    
    
    print(f"nTotal coaching time: {time.time()-t0:.1f}s")
    
    
    print("n" + "="*60)
    print("SECTION 7: Save & load mannequin weights")
    print("="*60)
    
    
    eqx.tree_serialise_leaves("model_weights.eqx", mannequin)
    
    
    key, mk2 = jax.random.break up(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(mannequin, eqx.is_array))[0]
     - jax.tree_util.tree_leaves(eqx.filter(model_loaded, eqx.is_array))[0]
    ))
    print(f"Max weight distinction after reload: {diff:.2e}  (needs to be 0.0)")
    
    
    fig, axes = plt.subplots(1, 2, figsize=(12, 4))
    
    
    axes[0].plot(train_losses, label="Prepare MSE", coloration="#4C72B0")
    axes[0].plot(val_losses,   label="Val MSE",   coloration="#DD8452", linestyle="--")
    axes[0].set_xlabel("Epoch")
    axes[0].set_ylabel("MSE")
    axes[0].set_title("Coaching curves")
    axes[0].legend()
    axes[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(mannequin)(x_plot)
    
    
    axes[1].scatter(X_val[:100], Y_val[:100], s=10, alpha=0.4, coloration="grey", label="Information")
    axes[1].plot(x_plot, y_true, coloration="#4C72B0",  linewidth=2, label="True f(x)")
    axes[1].plot(x_plot, y_pred, coloration="#DD8452", linewidth=2, linestyle="--", label="Predicted")
    axes[1].set_xlabel("x")
    axes[1].set_ylabel("y")
    axes[1].set_title("Sine regression match")
    axes[1].legend()
    axes[1].grid(True, alpha=0.3)
    
    
    plt.tight_layout()
    plt.savefig("equinox_tutorial.png", dpi=150)
    plt.present()
    print("nDone! Plot saved to equinox_tutorial.png")
    
    
    print("n" + "="*60)
    print("BONUS: eqx.filter_jit + form inference debug tip")
    print("="*60)
    
    
    jaxpr = jax.make_jaxpr(jax.vmap(mannequin))(x_plot)
    n_eqns = len(jaxpr.jaxpr.eqns)
    print(f"Compiled ResNetMLP jaxpr has {n_eqns} equations (ops) for batch enter {x_plot.form}")
    BATCH  = 128
    EPOCHS = 30
    steps_per_epoch = len(X_train) // BATCH
    train_losses, val_losses = [], []
    
    
    t0 = time.time()
    for epoch in vary(EPOCHS):
       key, sk = jax.random.break up(key)
       perm = jax.random.permutation(sk, len(X_train))
       X_s, Y_s = X_train[perm], Y_train[perm]
    
    
       epoch_loss = 0.0
       for step in vary(steps_per_epoch):
           xb = X_s[step*BATCH:(step+1)*BATCH]
           yb = Y_s[step*BATCH:(step+1)*BATCH]
           mannequin, opt_state, loss = train_step(mannequin, opt_state, xb, yb)
           epoch_loss += loss.merchandise()
    
    
       val_loss = consider(mannequin, X_val, Y_val).merchandise()
       train_losses.append(epoch_loss / steps_per_epoch)
       val_losses.append(val_loss)
    
    
       if (epoch + 1) % 5 == 0:
           print(f"Epoch {epoch+1:3d}/{EPOCHS}  "
                 f"train_loss={train_losses[-1]:.5f}  "
                 f"val_loss={val_losses[-1]:.5f}")
    
    
    print(f"nTotal coaching time: {time.time()-t0:.1f}s")
    
    
    print("n" + "="*60)
    print("SECTION 7: Save & load mannequin weights")
    print("="*60)
    
    
    eqx.tree_serialise_leaves("model_weights.eqx", mannequin)
    
    
    key, mk2 = jax.random.break up(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(mannequin, eqx.is_array))[0]
     - jax.tree_util.tree_leaves(eqx.filter(model_loaded, eqx.is_array))[0]
    ))
    print(f"Max weight distinction after reload: {diff:.2e}  (needs to be 0.0)")
    
    
    fig, axes = plt.subplots(1, 2, figsize=(12, 4))
    
    
    axes[0].plot(train_losses, label="Prepare MSE", coloration="#4C72B0")
    axes[0].plot(val_losses,   label="Val MSE",   coloration="#DD8452", linestyle="--")
    axes[0].set_xlabel("Epoch")
    axes[0].set_ylabel("MSE")
    axes[0].set_title("Coaching curves")
    axes[0].legend()
    axes[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(mannequin)(x_plot)
    
    
    axes[1].scatter(X_val[:100], Y_val[:100], s=10, alpha=0.4, coloration="grey", label="Information")
    axes[1].plot(x_plot, y_true, coloration="#4C72B0",  linewidth=2, label="True f(x)")
    axes[1].plot(x_plot, y_pred, coloration="#DD8452", linewidth=2, linestyle="--", label="Predicted")
    axes[1].set_xlabel("x")
    axes[1].set_ylabel("y")
    axes[1].set_title("Sine regression match")
    axes[1].legend()
    axes[1].grid(True, alpha=0.3)
    
    
    plt.tight_layout()
    plt.savefig("equinox_tutorial.png", dpi=150)
    plt.present()
    print("nDone! Plot saved to equinox_tutorial.png")
    
    
    print("n" + "="*60)
    print("BONUS: eqx.filter_jit + form inference debug tip")
    print("="*60)
    
    
    jaxpr = jax.make_jaxpr(jax.vmap(mannequin))(x_plot)
    n_eqns = len(jaxpr.jaxpr.eqns)
    print(f"Compiled ResNetMLP jaxpr has {n_eqns} equations (ops) for batch enter {x_plot.form}")



    Source link

    Naveed Ahmad

    Naveed Ahmad is a technology journalist and AI writer at ArticlesStock, covering artificial intelligence, machine learning, and emerging tech policy. Read his latest articles.

    Related Posts

    OpenAI says hackers stole some information after newest code safety concern

    14/05/2026

    Cerebras raises $5.5B, kicking off 2026’s IPO season with a bang

    14/05/2026

    Khosla Ventures is betting $10M on Ian Crosby, whose final startup, Bench, imploded

    14/05/2026
    Leave A Reply Cancel Reply

    Categories
    • AI
    Recent Comments
      Facebook X (Twitter) Instagram Pinterest
      © 2026 ThemeSphere. Designed by ThemeSphere.

      Type above and press Enter to search. Press Esc to cancel.