Skip to content

Quickstart

A model, trained

import torch
import kanforge as kf
from kanforge.torch import KAN

x = torch.rand(1000, 2) * 2 - 1
y = torch.sin(torch.pi * x[:, :1]) * x[:, 1:] ** 2

model = KAN([2, 5, 1], kf.BSpline(5, 3), coef_init="lecun")
opt = torch.optim.Adam(model.parameters(), lr=1e-2)
for step in range(1000):
    opt.zero_grad()
    loss = ((model(x) - y) ** 2).mean()
    loss.backward()
    opt.step()
    if step == 200:
        model.update_grid(x)                          # grids follow the data
        opt = torch.optim.Adam(model.parameters(), lr=1e-2)

Any basis, any backend

model = KAN([2, 5, 1], kf.Chebyshev(6))              # or "fourier", kf.Jacobi(6, 0.5, 0.5), ...

import mlx.core as mx
from kanforge.mlx import KAN as MLXKAN
mlx_model = MLXKAN([2, 5, 1], "bspline")

import kanforge
kanforge.save(model, "model.npz")
jax_model = kanforge.load("model.npz", backend="jax")

Look inside

from kanforge import interpret as ki

pruned = ki.prune(model, x)
ki.auto_symbolic(pruned, x)
print(ki.symbolic_formula(pruned, ["x", "y"]))

Ship it

from kanforge.export.onnx_export import export_onnx
export_onnx(model, "model.onnx", x, size=256, bits=8)