如何为神经 ODE 的损失函数添加 L1 惩罚?
How to add an L1 penalty to the loss function for Neural ODEs?
我一直在尝试将微分方程组拟合到我拥有的一些数据,并且有 18 个参数可以拟合,但是理想情况下,其中一些参数应该 zero/go 到零。在谷歌搜索时,我遇到的是将 DE 层构建到神经网络中,并且我发现了一些带有 Julia 代码示例的 Github 回购协议,但是我对 Julia 和神经 ODE 都是新手。特别是,我一直在修改这个例子中的代码:
https://computationalmindset.com/en/neural-networks/experiments-with-neural-odes-in-julia.html
差异:我有一个包含 3 个 DE 的系统,而不是 2 个,我有 18 个参数,并且我导入了两个 CSV 文件来适应它,而不是生成一个玩具数据集来适应它。
我的困境:在使用 gooling 时,我遇到了 LASSO/L1 正则化,并希望通过向成本函数添加 L1 惩罚,我可以将一些参数“清零”。问题是我不明白如何修改成本函数来合并它。我现在的损失函数只是
function loss_func()
pred = net()
sum(abs2, truth[1] .- pred[1,:]) +
sum(abs2, truth[2] .- pred[2,:]) +
sum(abs2, truth[3] .- pred[3,:])
end
但我想将 L1 处罚纳入其中。对于 L1 回归,我遇到了成本函数的方程式:J′(θ;X,y) = J(θ;X,y)+aΩ(θ)
,其中“其中 θ
表示可训练参数,X
输入... y
[the ] 目标标签。a
是一个超参数,对范数惩罚的贡献进行加权”,对于 L1 正则化,惩罚是 Ω(θ) = ∣∣w∣∣ = ∑∣w∣
(来源:https://theaisummer.com/regularization/)。我知道 RHS 的第一项是损失 J(θ;X,y)
并且是我已经拥有的,a
是我选择的超参数,可以是 0.001、0.1、1、100000000 等,并且L1惩罚是参数绝对值的总和。我不明白的是我如何将 a∑∣w∣
项添加到我当前的函数中 - 我想将其编辑为如下所示:
function cost_func(lambda)
pred = net()
penalty(lambda) = lambda * (sum(abs(param[1])) +
sum(abs(param[2])) +
sum(abs(param[3]))
)
sum(abs2, truth[1] .- pred[1,:]) +
sum(abs2, truth[2] .- pred[2,:]) +
sum(abs2, truth[3] .- pred[3,:]) +
penalty(lambda)
end
其中 param[1], param[2], param[3]
指的是我正在尝试学习的 DE u[1], u[2], u[3]
的参数。我不知道这个逻辑是否正确或实现它的正确方法,而且我也不知道 how/where 我会访问学习到的参数。我怀疑答案可能就在这段代码中的某处
callback_func = function ()
loss_value = loss_func()
println("Loss: ", loss_value)
end
fparams = Flux.params(p)
Flux.train!(loss_func, fparams, data, optimizer, cb = callback_func);
但我不确定甚至不知道如何使用它,如果它是答案的话。
我一直在弄乱这个,并查看了其他一些 NODE 实现 (this one in particular) 并调整了我的成本函数,使其成为:
function cost_fnct(param)
prob = ODEProblem(model, u0, tspan, param)
prediction = Array(concrete_solve(prob, Tsit5(), p = param, saveat = trange))
loss = Flux.mae(prediction, data)
penalty = sum(abs, param)
loss + lambda*penalty
end;
其中lambda
为调优参数,使用L1惩罚为参数绝对值之和的定义。然后,进行训练:
lambda = 0.01
resinit = DiffEqFlux.sciml_train(cost_fnct, p, ADAM(), maxiters = 3000)
res = DiffEqFlux.sciml_train(cost_fnct, resinit.minimizer, BFGS(initial_stepnorm = 1e-5))
其中 p
只是我的参数“猜测”的初始值,即与我尝试拟合的参数数量长度相同的矢量。
如果你看的是第一个link我原来的post(here),你可以重新定义损失函数加上这个惩罚项然后定义lambda
回调函数前及后续训练:
lambda = 0.01
callback_func = function ()
loss_value = cost_fnct()
println("Loss: ", loss_value)
println("\nLearned parameters: ", p)
end
fparams = Flux.params(p)
Flux.train!(cost_fnct, fparams, data, optimizer, cb = callback_func);
None 当然,其中包括任何类型的交叉验证和调整参数优化!我会继续接受我对我的问题的回答,因为据我所知,未回答的问题会被推送以鼓励回答,我想避免堵塞标签,但如果有人有不同的解决方案,或想发表评论,请随时继续这样做。
我一直在尝试将微分方程组拟合到我拥有的一些数据,并且有 18 个参数可以拟合,但是理想情况下,其中一些参数应该 zero/go 到零。在谷歌搜索时,我遇到的是将 DE 层构建到神经网络中,并且我发现了一些带有 Julia 代码示例的 Github 回购协议,但是我对 Julia 和神经 ODE 都是新手。特别是,我一直在修改这个例子中的代码:
https://computationalmindset.com/en/neural-networks/experiments-with-neural-odes-in-julia.html
差异:我有一个包含 3 个 DE 的系统,而不是 2 个,我有 18 个参数,并且我导入了两个 CSV 文件来适应它,而不是生成一个玩具数据集来适应它。
我的困境:在使用 gooling 时,我遇到了 LASSO/L1 正则化,并希望通过向成本函数添加 L1 惩罚,我可以将一些参数“清零”。问题是我不明白如何修改成本函数来合并它。我现在的损失函数只是
function loss_func()
pred = net()
sum(abs2, truth[1] .- pred[1,:]) +
sum(abs2, truth[2] .- pred[2,:]) +
sum(abs2, truth[3] .- pred[3,:])
end
但我想将 L1 处罚纳入其中。对于 L1 回归,我遇到了成本函数的方程式:J′(θ;X,y) = J(θ;X,y)+aΩ(θ)
,其中“其中 θ
表示可训练参数,X
输入... y
[the ] 目标标签。a
是一个超参数,对范数惩罚的贡献进行加权”,对于 L1 正则化,惩罚是 Ω(θ) = ∣∣w∣∣ = ∑∣w∣
(来源:https://theaisummer.com/regularization/)。我知道 RHS 的第一项是损失 J(θ;X,y)
并且是我已经拥有的,a
是我选择的超参数,可以是 0.001、0.1、1、100000000 等,并且L1惩罚是参数绝对值的总和。我不明白的是我如何将 a∑∣w∣
项添加到我当前的函数中 - 我想将其编辑为如下所示:
function cost_func(lambda)
pred = net()
penalty(lambda) = lambda * (sum(abs(param[1])) +
sum(abs(param[2])) +
sum(abs(param[3]))
)
sum(abs2, truth[1] .- pred[1,:]) +
sum(abs2, truth[2] .- pred[2,:]) +
sum(abs2, truth[3] .- pred[3,:]) +
penalty(lambda)
end
其中 param[1], param[2], param[3]
指的是我正在尝试学习的 DE u[1], u[2], u[3]
的参数。我不知道这个逻辑是否正确或实现它的正确方法,而且我也不知道 how/where 我会访问学习到的参数。我怀疑答案可能就在这段代码中的某处
callback_func = function ()
loss_value = loss_func()
println("Loss: ", loss_value)
end
fparams = Flux.params(p)
Flux.train!(loss_func, fparams, data, optimizer, cb = callback_func);
但我不确定甚至不知道如何使用它,如果它是答案的话。
我一直在弄乱这个,并查看了其他一些 NODE 实现 (this one in particular) 并调整了我的成本函数,使其成为:
function cost_fnct(param)
prob = ODEProblem(model, u0, tspan, param)
prediction = Array(concrete_solve(prob, Tsit5(), p = param, saveat = trange))
loss = Flux.mae(prediction, data)
penalty = sum(abs, param)
loss + lambda*penalty
end;
其中lambda
为调优参数,使用L1惩罚为参数绝对值之和的定义。然后,进行训练:
lambda = 0.01
resinit = DiffEqFlux.sciml_train(cost_fnct, p, ADAM(), maxiters = 3000)
res = DiffEqFlux.sciml_train(cost_fnct, resinit.minimizer, BFGS(initial_stepnorm = 1e-5))
其中 p
只是我的参数“猜测”的初始值,即与我尝试拟合的参数数量长度相同的矢量。
如果你看的是第一个link我原来的post(here),你可以重新定义损失函数加上这个惩罚项然后定义lambda
回调函数前及后续训练:
lambda = 0.01
callback_func = function ()
loss_value = cost_fnct()
println("Loss: ", loss_value)
println("\nLearned parameters: ", p)
end
fparams = Flux.params(p)
Flux.train!(cost_fnct, fparams, data, optimizer, cb = callback_func);
None 当然,其中包括任何类型的交叉验证和调整参数优化!我会继续接受我对我的问题的回答,因为据我所知,未回答的问题会被推送以鼓励回答,我想避免堵塞标签,但如果有人有不同的解决方案,或想发表评论,请随时继续这样做。