大约一个月前,我问了一个关于在训练神经微分方程时更好地收敛的策略的问题。从那以后,我已经使用给我的建议使该示例起作用,但是当我将相同的建议应用于更困难的模型时,我又被卡住了。我所有的代码都在 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 个点左右来提高速度,使用更多并不能提高结果)。数据如下所示:训练数据
我正在训练的 UDE 是
function SIRx_ude!(du, u, p, t)
μ, γ = Float32.([1/50, 365/22])
S,I,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 个输出的单个神经网络,但它速度较慢并且性能也没有更好。我还尝试首先对网络的输入进行规范化,但除了减慢速度之外,它并没有显着的区别。
我试过的
- 单拍 网络正好适合一条穿过数据中间的线。即使我在损失函数中对早期数据点进行更多加权,也会发生这种情况。单次训练
- 多重射击 我得到的最好结果是多重射击。如此处所见,它不仅仅是拟合一条直线,而且也不是完全拟合数据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-stage 搭配训练在第 1 阶段效果非常好,但在第 2 阶段实际上并没有提高性能(我在第 2 阶段尝试过单拍和多拍)。最后,mini-batching 的效果与单次拍摄一样好(也就是说不是很好),但速度要快得多。
我的问题
总之,我不知道该尝试什么。有很多策略,每个策略都有很多可以调整的参数。我需要一种更准确地诊断问题的方法,以便更好地决定如何进行。如果有人有此类问题的经验,我会很感激我能得到的任何建议或指导。