CVKAN: Complex-Valued Kolmogorov-Arnold Networks

May 11, 2026 · View on GitHub

Authors: Matthias Wolff, Florian Eilers, Xiaoyi Jiang
University of Münster, Department of Computer Science

Conference Paper: M. Wolff, F. Eilers and X. Jiang, "CVKAN: Complex-Valued Kolmogorov-Arnold Networks," 2025 International Joint Conference on Neural Networks (IJCNN), Rome, Italy, 2025, pp. 1-9, doi: 10.1109/IJCNN64981.2025.11227425

Available on IEEEXplore: https://ieeexplore.ieee.org/document/11227425

Link to arXiv Paper: https://arxiv.org/abs/2502.02417


Abstract

In this work we propose CVKAN, a complex-valued Kolmogorov-Arnold Network (KAN), to join the intrinsic interpretability of KANs and the advantages of Complex-Valued Neural Networks (CVNNs). We show how to transfer a KAN and the necessary associated mechanisms into the complex domain. To confirm that CVKAN meets expectations we conduct experiments on symbolic complex-valued function fitting and physically meaningful formulae as well as on a more realistic dataset from knot theory. Our proposed CVKAN is more stable and performs on par or better than real-valued KANs while requiring less parameters and a shallower network architecture, making it more explainable.

<CVKAN Plot>


Changes / Issues after Paper submission

  • Learning rate for CVKAN (and probably for real-valued KANs as well) was too small. Increasing it from $0.01 to \0.1$ made results far more stable and better in combination with validation LR scheduling. Also see our follow-up paper Clifford Kolmogorov-Arnold Networks as well as the corresponding Github-Repository. Simply increasing the LR here with implemented step LR scheduling might not yield satisfying results.
  • Circuit dataset training was not very successful. The formula blows up if the denominator is close to zero and produces outliers. The formula is made for physical quantities and simply inputting a random range of [2,2][-2,2] for each variable leads to unrealistic settings. Better approach would be to sample physically plausible values, then calculate the label (voltage URLU_{RL}), then normalize input values to range [2,2][-2,2].
  • Model should be put in .eval() mode for evaluation runs. Otherwise running means of BatchNorms are also updated during evaluation passes causing some minor information leakage.

Table of Contents


How to use

See demo.py

Install

pip install cvkan

Imports

from cvkan import CVKANWrapper, train_kans, KANPlot
from cvkan.models.CVKAN import Norms
from cvkan.utils import create_complex_dataset, CSVDataset
from cvkan.utils.loss_functions import MSE, MAE

Create Dataset

# Generate dataset for f(z)=(z$1^{2}$ + z$2^{2}$)^2
f_squaresquare = lambda x: (x[:,0]**2 + x[:,1]**2)**2
# create dataset (this is a dictionary with keys 'train_input', 'train_label', 'test_input' and 'test_label', each
# containing a Tensor as value)
dataset = create_complex_dataset(f=f_squaresquare, n_var=2, ranges=[-1,1], train_num=5000, test_num=1000)
# convert dataset to CSVDataset object for easier handling later
dataset = CSVDataset(dataset, input_vars=["z1", "z2"], output_vars=["(z$1^{2}$ + z$2^{2}$)^2"], categorical_vars=[])

CVKAN

# create CVKAN model. Note that this is CVKANWrapper, which is basically the same as CVKAN but with additional
# features for plotting later on
cvkan_model = CVKANWrapper(layers_hidden=[2,1,1], num_grids=8, use_norm=Norms.BatchNorm, grid_mins=-2, grid_maxs=2, csilu_type="complex_weight")



# train cvkan_model on dataset
results = train_kans(cvkan_model,  # model
           dataset,  # dataset
           loss_fn_backprop=MSE(),  # loss function to use for backpropagation
           loss_fns={"mse": MSE(), "mae": MAE()},  # loss function dictionary to evaluate the model on
           epochs=500,  # epochs to train for
           batch_size=1000,  # batch size for training
           kan_explainer=None,  # we could specify an explainer to make edge's transparency represent edge's relevance
           add_softmax_lastlayer=False,  # we don't need softmax after last layer (as we are doing regression)
           last_layer_output_real=False  # last layer should also have complex-valued output (regression)
           )
print("results of training: \n", results)

Plotting

# plot the model
kan_plotter = KANPlot(cvkan_model,
                      kan_explainer=None,
                      input_featurenames=dataset.input_varnames,
                      output_names=dataset.output_varnames,
                      complex_valued=True,
                      )
kan_plotter.plot_all()

In rare occasions the random initialization of the weights is suboptimal, which leads to the model not training correctly. If you do not end up with an image similar to the one displayed above or if the resulting Test MSE is way worse than 0.05, please run again.