[KAN学习日记](1)构建基本的网络框架以及网格细化

教程地址:https://github.com/KindXiaoming/pykan/blob/master/README.md
本系列文章用于记录自己学习过程

一.如何利用网格细化最大化KAN拟合函数的能力

(1)初始化模型和创建数据集

from kan import *

# 初始化KAN,设置网格为3
model = KAN(width=[2, 1, 1], grid=3, k=3)

# 创建数据集
f = lambda x: torch.exp(torch.sin(torch.pi * x[:, [0]]) + x[:, [1]] ** 2)
dataset = create_dataset(f, n_var=2)

(2)使用不同网格的KAN模型对比
训练KAN(网格=3)

model.train(dataset, opt="LBFGS", steps=20)

现在初始化一个网格大小为10的KAN模型,并从之前的模型进行初始化:

# initialize a more fine-grained KAN with G=10
model2 = KAN(width=[2,1,1], grid=10, k=3)
# initialize model2 from model
model2.initialize_from_another_model(model, dataset['train_input']);

用更细粒度的KAN模型训练数据集:(网格=10)

model2.train(dataset, opt="LBFGS", steps=20);

两个不同细粒度KAN模型loss对比
在这里插入图片描述
损失变低,说明效果更好.现在可以迭代地使网格更加细化。
(3)迭代网格细化
我们可以通过逐步增加网格大小,观察损失变化情况:

grids = np.array([5, 10, 20, 50, 100])

train_losses = []
test_losses = []
steps = 50
k = 3

for i in range(grids.shape[0]):
    if i == 0:
        model = KAN(width=[2, 1, 1], grid=grids[i], k=k)
    if i != 0:
        model = KAN(width=[2, 1, 1], grid=grids[i], k=k).initialize_from_another_model(model, dataset['train_input'])
    results = model.train(dataset, opt="LBFGS", steps=steps, stop_grid_update_step=30)
    train_losses += results['train_loss']
    test_losses += results['test_loss']

训练过程中的损失变化如下:
在这里插入图片描述
(4)可视化展现训练损失和测试损失的动态变化

plt.plot(train_losses)
plt.plot(test_losses)
plt.legend(['train', 'test'])
plt.ylabel('RMSE')
plt.xlabel('step')
plt.yscale('log')
plt.show()

请添加图片描述
最后,我们可以观察参数数量与损失的关系:

n_params = 3 * grids
train_vs_G = train_losses[(steps-1)::steps]
test_vs_G = test_losses[(steps-1)::steps]

plt.plot(n_params, train_vs_G, marker="o")
plt.plot(n_params, test_vs_G, marker="o")
plt.plot(n_params, 100 * n_params**(-4.), ls="--", color="black")
plt.xscale('log')
plt.yscale('log')
plt.legend(['train', 'test', r'$N^{-4}$'])
plt.xlabel('number of params')
plt.ylabel('RMSE')
plt.show()

请添加图片描述

二.如何使用深层KAN模型来解决复杂任务

Kolmogorov-Arnold(KA)定理原本表示仅需要两层函数组合(内函数和外函数),但这些函数可能是非光滑甚至是分形的。我们将KA表示法推广到任意深度。一个使用光滑激活函数的两层KAN模型无法处理的例子需要至少三层KAN模型才能完成。
例如:
在这里插入图片描述

在本教程中,我们将展示如何使用深层KAN模型来解决复杂任务,并比较两层和三层KAN模型的性能。

(1)创建和训练三层KAN模型
创建模型:创建一个2D输入、1D输出,5个隐藏神经元的三层KAN模型,使用三次样条(k=3)和5个网格间隔(grid=5)。

model = KAN(width=[4, 2, 1, 1], grid=3, k=3, seed=0)
f = lambda x: torch.exp((torch.sin(torch.pi * (x[:, [0]]**2 + x[:, [1]]**2)) + torch.sin(torch.pi * (x[:, [2]]**2 + x[:, [3]]**2))) / 2)
dataset = create_dataset(f, n_var=4, train_num=3000)

训练模型

model.train(dataset, opt="LBFGS", steps=20, lamb=0.001, lamb_entropy=2.)

模型可视化:

model.plot(beta=10)
plt.show()

请添加图片描述

调整网格并再次训练:

grids = [3, 5, 10, 20, 50]
train_rmse = []
test_rmse = []

for grid in grids:
    model = KAN(width=[4, 2, 1, 1], grid=grid, k=3, seed=0).initialize_from_another_model(model, dataset['train_input'])
    results = model.train(dataset, opt="LBFGS", steps=50, stop_grid_update_step=30)
    train_rmse.append(results['train_loss'][-1].item())
    test_rmse.append(results['test_loss'][-1].item())

可视化结果:

n_params = np.array(grids) * (4*2 + 2*1 + 1*1)
plt.plot(n_params, train_rmse, marker="o")
plt.plot(n_params, test_rmse, marker="o")
plt.plot(n_params, 10000*n_params**(-4.), color="black", ls="--")
plt.legend(['train', 'test', r'$N^{-4}$'], loc="lower left")
plt.xscale('log')
plt.yscale('log')
plt.show()

print(train_rmse)
print(test_rmse)

请添加图片描述
(2)两层KAN模型示例
创建和训练两层KAN模型
创建模型:创建一个2D输入、1D输出,9个隐藏神经元的两层KAN模型,使用三次样条(k=3)和5个网格间隔(grid=5)

model = KAN(width=[4, 9, 1], grid=3, k=3, seed=0)
f = lambda x: torch.exp((torch.sin(torch.pi * (x[:, [0]]**2 + x[:, [1]]**2)) + torch.sin(torch.pi * (x[:, [2]]**2 + x[:, [3]]**2))) / 2)
dataset = create_dataset(f, n_var=4, train_num=3000)

训练模型并可视化

model.train(dataset, opt="LBFGS", steps=20, lamb=0.001, lamb_entropy=2.)
model.plot(beta=10)
plt.show()

请添加图片描述

调整网格并再次训练:

grids = [3, 5, 10, 20, 50]
train_rmse = []
test_rmse = []

for grid in grids:
    model = KAN(width=[4, 9, 1], grid=grid, k=3, seed=0).initialize_from_another_model(model, dataset['train_input'])
    results = model.train(dataset, opt="LBFGS", steps=50, stop_grid_update_step=30)
    train_rmse.append(results['train_loss'][-1].item())
    test_rmse.append(results['test_loss'][-1].item())

可视化结果:

n_params = np.array(grids) * (4*9 + 9*1)
plt.plot(n_params, train_rmse, marker="o")
plt.plot(n_params, test_rmse, marker="o")
plt.plot(n_params, 300*n_params**(-2.), color="black", ls="--")
plt.legend(['train', 'test', r'$N^{-4}$'], loc="lower left")
plt.xscale('log')
plt.yscale('log')
plt.show()

print(train_rmse)
print(test_rmse)

请添加图片描述

通过上述示例可以看出,三层KAN模型在处理复杂任务时比两层KAN模型表现更好。这证明了增加模型深度能够显著提升模型的表达能力和性能。

通过不断调整网格参数和模型架构,我们可以进一步优化模型的表现。希望本教程能够帮助你更好地理解和应用深层KAN模型

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值