如何为神经ODE的损失函数添加L1惩罚?

我一直在尝试将一组微分方程拟合到我拥有的一些数据上,这些方程有18个参数需要拟合,但理想情况下,其中一些参数应该为零或趋向于零。在谷歌搜索过程中,我发现了一种将DE层构建到神经网络中的方法,并且我找到了几个包含Julia代码示例的Github仓库,然而我对Julia和神经ODE都很陌生。特别是,我一直在修改这个示例中的代码:

https://computationalmindset.com/en/neural-networks/experiments-with-neural-odes-in-julia.html

不同之处在于:我有3个DE系统,而不是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/)。我理解右侧的第一项是损失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]指的是我尝试学习的DEu[1], u[2], u[3]的参数。不过,我不确定这种逻辑是否正确或者是否是实现它的正确方式,而且我不知道如何/在哪里访问学习到的参数。我怀疑答案可能在于这段代码的某个地方

callback_func = function () loss_value = loss_func() println("Loss: ", loss_value)endfparams = Flux.params(p)Flux.train!(loss_func, fparams, data, optimizer, cb = callback_func);

但我不确定或者即使这是答案,我也不知道如何使用它。


回答:

我一直在摆弄这个,并且查看了其他一些NODE实现(特别是这个),并调整了我的成本函数,使其变为:

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.01resinit = DiffEqFlux.sciml_train(cost_fnct, p, ADAM(), maxiters = 3000)res = DiffEqFlux.sciml_train(cost_fnct, resinit.minimizer, BFGS(initial_stepnorm = 1e-5))

其中p最初只是我的参数“猜测”,即一个与我尝试拟合的参数数量长度相同的全1向量。

如果你在查看我最初帖子中的第一个链接(这里),你可以重新定义损失函数以添加这个惩罚项,然后在回调函数和后续训练之前定义lambda

lambda = 0.01callback_func = function ()     loss_value = cost_fnct()     println("Loss: ", loss_value)     println("\nLearned parameters: ", p)endfparams = Flux.params(p)Flux.train!(cost_fnct, fparams, data, optimizer, cb = callback_func);

当然,这一切都不包括任何形式的交叉验证和调节参数优化!我将接受我的问题的回答,因为我了解到未回答的问题会被推动以鼓励回答,我希望避免堵塞标签,但如果有人有不同的解决方案,或者想评论,请随时继续进行。

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注