如何解决使用 sciml_train
大约一个月前,我问了一个关于训练神经微分方程时更好收敛的策略的问题。从那以后,我使用给定的建议得到了该示例,但是当我将相同的建议应用于更困难的模型时,我再次陷入困境。我的所有代码都在 Julia 中,主要使用 DiffEqFlux 库。为了让这篇文章尽可能简短,我不会分享我尝试过的所有代码的所有代码,但如果有人想要访问它以进行故障排除,我可以提供它。
我想做什么
我尝试学习的数据来自 SIRx 模型:
function SIRx!(du,u,p,t)
β,μ,γ,a,b = Float32.([280,1/50,365/22,100,0.05])
S,I,x = u
du[1] = μ*(1-x) - β*S*I - μ*S
du[2] = β*S*I - (μ+γ)*I
du[3] = a*I - b*x
nothing
end;
我使用的初始条件是 u0 = Float32.([0.062047128,1.3126149f-7,0.9486445]);
。我生成了从 t=0 到 25 的数据,每 0.02 采样一次(在训练中,我只使用每 20 个点左右的速度,使用更多并不会改善结果)。数据如下所示:Training Data
我正在培训的 UDE 是
function SIRx_ude!(du,t)
μ,γ = Float32.([1/50,365/22])
S,x = u
du[1] = μ*(1-x) - μ*S + ann_dS(u,@view p[1:lenS])[1]
du[2] = -(μ+γ)*I + ann_dI(u,@view p[lenS+1:lenS+lenI])[1]
du[3] = ann_dx(u,@view p[lenI+1:end])[1]
nothing
end;
每个神经网络 (ann_dS,ann_dI,ann_dx
) 都使用 FastChain(FastDense(3,20,tanh),FastDense(20,1))
定义。我尝试使用具有 3 个输入和 3 个输出的单个神经网络,但它速度较慢并且性能也没有提高。我还尝试先对网络的输入进行规范化,但除了减慢速度之外,它并没有产生重大影响。
我的尝试
- 单拍 网络只适合穿过数据中间的一条线。即使我在损失函数中对较早的数据点加权更多,也会发生这种情况。 Single-shot Training
- 多重射击 我最好的结果是多次射击。如此处所见,它不仅仅是拟合直线,也不是完全拟合数据Multiple Shooting Result。我尝试了从 0.1 到 100 的连续性术语和从 3 到 30 的组大小,但没有显着差异。
- 各种其他策略 我还尝试迭代地增加拟合度、使用搭配的 2 阶段训练和小批量,如下所述:https://diffeqflux.sciml.ai/dev/examples/local_minima、https://diffeqflux.sciml.ai/dev/examples/collocation/、https://diffeqflux.sciml.ai/dev/examples/minibatch/。迭代增长拟合在前几次迭代中效果很好,但随着长度的增加,它又回到拟合直线。 2阶段搭配训练对于阶段1效果很好,但实际上并没有提高第二阶段的表现(我已经为第二阶段尝试了单拍和多拍)。最后,小批量处理的效果与单次拍摄一样好(也就是说不是很好),但速度要快得多。
我的问题
总而言之,我不知道该尝试什么。有很多策略,每个策略都有很多可以调整的参数。我需要一种更准确地诊断问题的方法,以便我可以更好地决定如何继续。如果有人有此类问题的经验,我会很感激我能得到的任何建议或指导。
解决方法
这不是一个很好的 SO 问题,因为它更具探索性。您是否降低了 ODE 容差?这将改善您的梯度计算,这可能会有所帮助。你用的是什么激活函数?我会使用 softplus
之类的东西而不是 tanh
这样你就不会出现饱和行为。您是否对特征值进行了缩放并考虑了 the issues explored in the stiff neural ODE paper?更大的神经网络?不同的学习率?亚当?等
这更适合于像 the JuliaLang Discourse 这样的论坛进行讨论。我们可以继续那里,因为如果没有来回走动,将不会有成果。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。