Neural network 如何在DifferenceQflux.lj neuralODE中创建任意参数化层?Julia Julialang Flux.jl

Neural network 如何在DifferenceQflux.lj neuralODE中创建任意参数化层?Julia Julialang Flux.jl,neural-network,julia,ode,Neural Network,Julia,Ode,我能够使用Flux.jl和DiffEqFlux.jl在julia(1.3和1.2)中创建和优化neuralODEs,但在一个重要的一般情况下失败了 工作原理: 我可以训练神经网络参数,如果它是建立在 提供通量.jl层,如致密() 我可以在网络链中包含任意函数作为一个层,例如x->x.*x 失败的地方: 然而,如果任意函数有我想要训练的参数,那么通量。列车不会调整这些参数,从而导致故障 我曾尝试跟踪这些添加的参数,并将其包含在提供给培训系统的参数列表中,但它忽略了这些参数,并且这些参数保持不变 文

我能够使用Flux.jl和DiffEqFlux.jl在julia(1.3和1.2)中创建和优化neuralODEs,但在一个重要的一般情况下失败了

工作原理:

  • 我可以训练神经网络参数,如果它是建立在 提供通量.jl层,如致密()
  • 我可以在网络链中包含任意函数作为一个层,例如x->x.*x
  • 失败的地方: 然而,如果任意函数有我想要训练的参数,那么通量。列车不会调整这些参数,从而导致故障

    我曾尝试跟踪这些添加的参数,并将其包含在提供给培训系统的参数列表中,但它忽略了这些参数,并且这些参数保持不变

    文档非常隐晦地说,可以在层上使用Flux@functor来确保跟踪其参数。然而,直到版本0.10.0,functor才包含在Flux中,并且Flux的唯一版本与DifferyQflux中的NeuralODEs兼容是0.9.0

    下面是一个我想使用的两层神经网络的玩具示例

    p = param([1.0])
    dudt = chain( x -> p[1]*x.*x, Dense(2,2) )
    ps = Flux.params(dudt)
    
    然后我在这上面用通量火车。当我这样做的时候,参数p是不变的,但是稠密层中的参数是不变的

    我已经尝试过明确地包括这样的内容

    ps = Flux.Params([p,dudt])
    
    但这有同样的结果和同样的问题

    我想我需要做的是构建一个带有关联函数的结构,该关联函数实现

    x->p[1]*x*x 
    
    然后对这个函数调用@functor。然后可以在链中使用该结构

    但正如我所指出的,带有@functor的Flux版本与任何版本的DiffEqFlux都不兼容

    所以我需要一种方法让flux注意我的自定义参数,而不仅仅是Dense()中的参数


    怎么做?

    我想我知道你的问题是什么,但是如果我在这里回答了错误的问题,请澄清。问题在于
    p
    仅从全局引用中获取,因此在伴随词中没有区分。2020年处理这一问题的更好方法是使用
    FastChain
    FastChan
    接口,因此这是一种很好的方法,可以使您的神经网络将任意函数与参数结合起来。下面是它的样子:

    using DifferentialEquations
    using Flux, Zygote
    using DiffEqFlux
    
    x = Float32[2.; 0.]
    p = Float32[2.0]
    tspan = (0.0f0,1.0f0)
    
    mylayer(x,p) = p[1]*x
    DiffEqFlux.paramlength(::typeof(mylayer)) = 1
    DiffEqFlux.initial_params(::typeof(mylayer)) = rand(Float32,1)
    
    dudt = FastChain(FastDense(2,50,tanh),FastDense(50,2),mylayer)
    p = DiffEqFlux.initial_params(dudt)
    function f(u,p,t)
        dudt(u,p)
    end
    ex_neural_ode(x,p) = solve(ODEProblem(f,x,tspan,p),Tsit5())
    solve(ODEProblem(f,x,tspan,p),Tsit5())
    
    du0,dp = Zygote.gradient((x,p)->sum(ex_neural_ode(x,p)),x,p)
    
    其中
    p
    的最后一个值是
    mylayer
    p
    的一个参数。或者您可以直接使用Flux:

    using DifferentialEquations
    using Flux, Zygote
    using DiffEqFlux
    
    x = Float32[2.; 0.]
    p2 = Float32[2.0]
    tspan = (0.0f0,1.0f0)
    
    dudt = Chain(Dense(2,50,tanh),Dense(50,2))
    p,re = Flux.destructure(dudt)
    function f(u,p,t)
        re(p[1:end-1])(u) |> x-> p[end]*x
    end
    ex_neural_ode() = solve(ODEProblem(f,x,tspan,[p;p2]),Tsit5())
    grads = Zygote.gradient(()->sum(ex_neural_ode()),Flux.params(x,p,p2))
    grads[x]
    grads[p]
    grads[p2]
    

    在DifferenceFlux与Flux 0.10.0和受精卵兼容的更新完成之前,这是不可能的,因为
    @Functor
    @chrisrackaukas需要这一点。您知道在'20年,现在是否有某种解决方案?我现在面临着完全相同的问题。