我一直在尝试将微分方程系统与我拥有的一些数据进行拟合,有18个参数需要拟合,但理想情况下,这些参数中的一些应该为零/变为零。在谷歌搜索时,我遇到的一件事是将DE层构建到神经网络中,我发现了一些带有Julia代码示例的Github代码库,但我对Julia和neural ODEs都是新手。特别是,我一直在修改这个示例中的代码:
https://computationalmindset.com/en/neural-networks/experiments-with-neural-odes-in-julia.html
不同之处:我有一个由3个DEs组成的系统,而不是2个,我有18个参数,并且我导入了两个CSV,其中包含要拟合的数据,而不是生成要拟合的玩具数据集。
我的两难境地:在谷歌的过程中,我遇到了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目标标签。a是一个超参数,它加权了范数惩罚的贡献”,而对于L1正则化,惩罚是Ω(θ) = ∣∣w∣∣ = ∑∣w∣ (来源:https://theaisummer.com/regularization/)。我知道RHS的第一个术语是loss 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]指的是我正在尝试学习的DEs u[1], u[2], u[3]的参数。我不知道这个逻辑是否正确,也不知道实现它的正确方式,我也不知道如何/在哪里访问学习到的参数。我怀疑答案可能就在这段代码的某个地方。
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);但我不确定,甚至不知道如何使用它,如果它是答案。
发布于 2021-11-10 22:54:11
我一直在处理这个问题,并查看了其他一些节点实现(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是初始的,只是我的参数“猜测”,即与我试图拟合的参数数量具有相同长度的1的向量。
如果您正在查看我在原始帖子(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);当然,所有这些都不包括任何类型的交叉验证和调优参数优化!我将继续接受我对我的问题的回答,因为我的理解是,未回答的问题会被推送以鼓励回答,我希望避免阻塞标签,但如果有人有不同的解决方案,或者想要评论,请随意继续并这样做。
https://stackoverflow.com/questions/69833351
复制相似问题