ARotting's picture
Publish Parameter-matched edge-spline KAN symbolic regression
a558330 verified
Raw
History Blame Contribute Delete
1.93 kB
from __future__ import annotations
import torch
from torch import nn
from torch.nn import functional as F
class LinearSplineLayer(nn.Module):
def __init__(
self,
input_dimensions: int,
output_dimensions: int,
grid_points: int,
) -> None:
super().__init__()
centers = torch.linspace(-1, 1, grid_points)
self.register_buffer("centers", centers)
self.spacing = float(centers[1] - centers[0])
self.coefficients = nn.Parameter(
torch.randn(output_dimensions, input_dimensions, grid_points) * 0.05
)
self.base_weight = nn.Parameter(
torch.randn(output_dimensions, input_dimensions) * 0.1
)
self.bias = nn.Parameter(torch.zeros(output_dimensions))
def forward(self, inputs: torch.Tensor) -> torch.Tensor:
distance = torch.abs(inputs[:, :, None] - self.centers)
basis = F.relu(1 - distance / self.spacing)
spline = torch.einsum("big,oig->bo", basis, self.coefficients)
return spline + F.linear(inputs, self.base_weight, self.bias)
class SplineKAN(nn.Module):
def __init__(self) -> None:
super().__init__()
self.first = LinearSplineLayer(2, 16, 14)
self.second = LinearSplineLayer(16, 1, 8)
def forward(self, inputs: torch.Tensor) -> torch.Tensor:
hidden = torch.tanh(self.first(inputs))
return self.second(hidden)
class MatchedMLP(nn.Module):
def __init__(self) -> None:
super().__init__()
self.network = nn.Sequential(
nn.Linear(2, 32),
nn.Tanh(),
nn.Linear(32, 16),
nn.Tanh(),
nn.Linear(16, 1),
)
def forward(self, inputs: torch.Tensor) -> torch.Tensor:
return self.network(inputs)
def parameter_count(model: nn.Module) -> int:
return sum(parameter.numel() for parameter in model.parameters())