From 41a775bb6860144396b34b4bb6843e31955940a7 Mon Sep 17 00:00:00 2001 From: Attilio Pittelli <70145737+leo-ai-for-trading@users.noreply.github.com> Date: Sun, 31 Mar 2024 12:16:08 +0200 Subject: [PATCH 01/10] update the sde_loop using the DifferentialEquations solver. --- src/DeepSplitting.jl | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/DeepSplitting.jl b/src/DeepSplitting.jl index 8a9945e4..1a2db288 100644 --- a/src/DeepSplitting.jl +++ b/src/DeepSplitting.jl @@ -1,3 +1,6 @@ +# import package +using DifferentialEquations + Base.copy(t::Tuple) = t # required for below function Base.copy(opt::O) where O<:Flux.Optimise.AbstractOptimiser return O([copy(getfield(opt,f)) for f in fieldnames(typeof(opt))]...) @@ -149,22 +152,26 @@ function solve( u = splitting_model(y0, y1, z, t) return sum(u.^2) / batch_size end + - # calculating SDE trajectories - function sde_loop!(y0, y1, dWall) - randn!(dWall) # points normally distributed for brownian motion - x0_sample!(y1) # points for initial conditions + # calculating the SDE trajectories - use the SDESolver + function sde_loop!(y0,y1,dWall) + x0_sample!(y1) #initial condition + randn!(dWall) #points normally distributed for brownian motion for i in 1:size(dWall,3) - t = ts[N + 1 - i] + t = ts[N + 1 - i] #this is dt dW = @view dWall[:,:,i] y0 .= y1 - y1 .= y0 .+ μ(y0,p,t) .* dt .+ σ(y0,p,t) .* sqrt(dt) .* dW + #y1 .= y0 .+ μ(y0,p,t) .* dt .+ σ(y0,p,t) .* sqrt(dt) .* dW + prob = SDEProblem(y0 .+ μ(y0,p,t) .* dt,σ(y0,p,t) .* sqrt(dt),x0_sample!(y1),t) + sol = solve(prob,EM(),dt=dt) if !isnothing(neumann_bc) y1 .= _reflect(y0, y1, neumann_bc[1], neumann_bc[2]) end end end + for net in 1:N # preallocate dWall dWall = similar(x0, d, batch_size, N + 1 - net) # for SDE @@ -174,6 +181,7 @@ function solve( # first of maxiters used for first nn, second used for the other nn _maxiters = length(maxiters) > 1 ? maxiters[min(net,2)] : maxiters[] + #modifying the sde_loop by replacing with StochasticDiffEq for λ in λs opt_net = copy(opt) # starting with a new optimiser state at each time step opt_net.eta = λ From 1f87acd63e32292e26a0fefc4b12e5bbfb53d6c2 Mon Sep 17 00:00:00 2001 From: Attilio Pittelli <70145737+leo-ai-for-trading@users.noreply.github.com> Date: Fri, 5 Apr 2024 13:09:38 +0200 Subject: [PATCH 02/10] Add files via upload update sde_loop function by removing the loop and use EnsembleProblem to calculate the trajectories --- DeepSplitting.jl | 252 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 252 insertions(+) create mode 100644 DeepSplitting.jl diff --git a/DeepSplitting.jl b/DeepSplitting.jl new file mode 100644 index 00000000..070ddd44 --- /dev/null +++ b/DeepSplitting.jl @@ -0,0 +1,252 @@ +# import package +using DifferentialEquations +using Flux + +Base.copy(t::Tuple) = t # required for below +function Base.copy(opt::O) where O<:Flux.Optimise.AbstractOptimiser + return O([copy(getfield(opt,f)) for f in fieldnames(typeof(opt))]...) +end + +""" + DeepSplitting(nn, K=1, opt = ADAM(0.01), λs = nothing, mc_sample = NoSampling()) + +Deep splitting algorithm. + +# Arguments +* `nn`: a [Flux.Chain](https://fluxml.ai/Flux.jl/stable/models/layers/#Flux.Chain), or more generally a [functor](https://github.com/FluxML/Functors.jl). +* `K`: the number of Monte Carlo integrations. +* `opt`: optimiser to be use. By default, `Flux.ADAM(0.01)`. +* `λs`: the learning rates, used sequentially. Defaults to a single value taken from `opt`. +* `mc_sample::MCSampling` : sampling method for Monte Carlo integrations of the non local term. Can be `UniformSampling(a,b)`, `NormalSampling(σ_sampling, shifted)`, or `NoSampling` (by default). + +# Example +```julia +hls = d + 50 # hidden layer size +d = 10 # size of the sample + +# Neural network used by the scheme +nn = Flux.Chain(Dense(d, hls, tanh), + Dense(hls,hls,tanh), + Dense(hls, 1, x->x^2)) + +alg = DeepSplitting(nn, K=10, opt = ADAM(), λs = [5e-3,1e-3], + mc_sample = UniformSampling(zeros(d), ones(d)) ) +``` +""" +struct DeepSplitting{NN,F,O,L,MCS} <: HighDimPDEAlgorithm + nn::NN + K::F + opt::O + λs::L + mc_sample!::MCS # Monte Carlo sample +end + +function DeepSplitting(nn; + K=1, + opt::O = ADAM(0.01), + λs::L = nothing, + mc_sample::MCSampling = NoSampling()) where {O <: Flux.Optimise.AbstractOptimiser, L <: Union{Nothing,Vector{N}} where N <: Number} + isnothing(λs) ? λs = [opt.eta] : nothing + DeepSplitting(nn, K, opt, λs, mc_sample) +end + +""" + solve(prob::PIDEProblem, + alg::DeepSplitting, + dt; + batch_size = 1, + abstol = 1f-6, + verbose = false, + maxiters = 300, + use_cuda = false, + cuda_device = nothing, + verbose_rate = 100) + +Returns a `PIDESolution` object. + +# Arguments +- `maxiters`: number of iterations per time step. Can be a tuple, where `maxiters[1]` is used for the training of the neural network used in the first time step (which can be long) and `maxiters[2]` is used for the rest of the time steps. +- `batch_size` : the batch size. +- `abstol` : threshold for the objective function under which the training is stopped. +- `verbose` : print training information. +- `verbose_rate` : rate for printing training information (every `verbose_rate` iterations). +- `use_cuda` : set to `true` to use CUDA. +- `cuda_device` : integer, to set the CUDA device used in the training, if `use_cuda == true`. +""" +function solve( + prob::PIDEProblem, + alg::DeepSplitting, + dt; + batch_size = 1, + abstol = 1f-6, + verbose = false, + maxiters = 300, + use_cuda = false, + cuda_device = nothing, + verbose_rate = 100 + ) + if use_cuda + if CUDA.functional() + @info "Training on CUDA GPU" + CUDA.allowscalar(false) + !isnothing(cuda_device) ? CUDA.device!(cuda_device) : nothing + _device = Flux.gpu + else + error("CUDA not functional, deactivate `use_cuda` and retry") + end + else + @info "Training on CPU" + _device = Flux.cpu + end + + ## unbin stuff + neumann_bc = prob.neumann_bc |> _device + x0 = prob.x |> _device + mc_sample! = alg.mc_sample! |> _device + x0_sample! = prob.x0_sample |> _device + + d = size(x0,1) + K = alg.K + opt = alg.opt + λs = alg.λs + g,f,μ,σ,p = prob.g,prob.f,prob.μ,prob.σ,prob.p + T = eltype(x0) + + # neural network model + nn = alg.nn |> _device + vi = g + # fix for deepcopy + vj = Flux.fmap(nn) do x + x isa AbstractArray && return copy(x) + x + end + ps = Flux.params(vj) + + dt = convert(T,dt) + ts = prob.tspan[1]:dt-eps(T):prob.tspan[2] + N = length(ts) - 1 + + usol = [g(x0 |>cpu)[]] + nns = Any[g] + losses = [Vector{eltype(prob.x)}() for net in 1:N+1] + + # allocating + x0_batch = repeat(x0, 1, batch_size) + y1 = similar(x0_batch) + y0 = similar(y1) + z = similar(x0, d, batch_size, K) # for MC non local integration + + # checking element types + eltype(mc_sample!) == T || !_integrate(mc_sample!) ? nothing : error( + "Element type of `mc_sample` not the same as element type of `x`") + + function splitting_model(y0, y1, z, t) + # TODO: for now hardcoded because of a bug in Zygote differentiation rules for adjoints + # vi_y1, ∇vi = Zygote.pullback(vi, y1) + # _int = reshape(sum(f(y1, z, vi_y1, vi(z), ∇vi(y1)[1], ∇vi(z)[1], p, t), dims = 3), 1, :) + ∇vi(x) = [0f0] + _int = reshape(sum(f(y1, z, vi(y1), vi(z), ∇vi(y1), ∇vi(z), p, t), dims = 3), 1, :) + return vj(y0) - (vi(y1) + dt * _int / K) + end + + function loss(y0, y1, z, t) + u = splitting_model(y0, y1, z, t) + return sum(u.^2) / batch_size + end + + + # calculating the SDE trajectories - use the SDESolver - it works + #function sde_loop!(y0,y1,dWall) + # x0_sample!(y1) #initial condition + # randn!(dWall) #points normally distributed for brownian motion + # for i in 1:size(dWall,3) + # t = ts[N + 1 - i] #this is dt + # dW = @view dWall[:,:,i] + # y0 .= y1 + # #y1 .= y0 .+ μ(y0,p,t) .* dt .+ σ(y0,p,t) .* sqrt(dt) .* dW + # prob = SDEProblem(y0 .+ μ(y0,p,t) .* dt,σ(y0,p,t) .* sqrt(dt),x0_sample!(y1),t) + # sol = solve(prob,EM(),dt=dt) + # if !isnothing(neumann_bc) + # y1 .= _reflect(y0, y1, neumann_bc[1], neumann_bc[2]) + # end + # end + #end + + # calculating the SDE trajectories - use the SDESolver + function sde_loop!(y0,y1,dWall) + x0_sample!(y1) #initial condition + randn!(dWall) #points normally distributed for brownian motion + y0 .= y1 + y1 .= y0 .+ μ(y0,p,t) .* dt .+ σ(y0,p,t) .* sqrt(dt) .* dW + prob = SDEProblem(y0 .+ μ(y0,p,t) .* dt,σ(y0,p,t) .* sqrt(dt),x0_sample!(y1),t) + ensembleprob = EnsembleProblem(prob) + sol = solve(ensembleprob, EnsembleSerial(), trajectories = 10) + if !isnothing(neumann_bc) + y1 .= _reflect(y0, y1, neumann_bc[1], neumann_bc[2]) + end + end + + + for net in 1:N + # preallocate dWall + dWall = similar(x0, d, batch_size, N + 1 - net) # for SDE + + verbose && println("Step $(net) / $(N) ") + t = ts[net] + # first of maxiters used for first nn, second used for the other nn + _maxiters = length(maxiters) > 1 ? maxiters[min(net,2)] : maxiters[] + + #modifying the sde_loop by replacing with StochasticDiffEq + for λ in λs + opt_net = copy(opt) # starting with a new optimiser state at each time step + opt_net.eta = λ + verbose && println("Training started with ", typeof(opt_net), " and λ :", opt_net.eta) + for epoch in 1:_maxiters + y1 .= x0_batch + # generating sdes + sde_loop!(y0, y1, dWall) + + if _integrate(mc_sample!) + # generating z for MC non local integration + mc_sample!(z, y1) + end + + # training + gs = Flux.gradient(ps) do + loss(y0, y1, z, t) + end + Flux.Optimise.update!(opt_net, ps, gs) # update parameters + + # report on training + if epoch % verbose_rate == 1 + l = loss(y0, y1, z, t) # explictly computing loss every verbose_rate + verbose && println("Current loss is: $l") + push!(losses[net], l) + if l < abstol + break + end + end + if epoch == maxiters + l = loss(y0, y1, z, t) + push!(losses[net+1], l) + verbose && println("Final loss for step $(net) / $(N) is: $l") + end + end + end + # saving + # fix for deepcopy + vi = Flux.fmap(vj) do x + x isa AbstractArray && return copy(x) + x + end + # vj = deepcopy(nn) + # ps = Flux.params(vj) + push!(usol, cpu(vi(reshape(x0, d, 1)))[]) + push!(nns, vi |> cpu) + end + + # return + sol = PIDESolution(x0, ts, losses, usol, nns) + return sol +end + From 62d0a868cd7ebf3361f3a5fa5c37ac62844315da Mon Sep 17 00:00:00 2001 From: Attilio Pittelli <70145737+leo-ai-for-trading@users.noreply.github.com> Date: Fri, 5 Apr 2024 13:12:31 +0200 Subject: [PATCH 03/10] update sde_loop function by removing the loop and use EnsembleProblem to calculate the trajectories --- src/DeepSplitting.jl | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/src/DeepSplitting.jl b/src/DeepSplitting.jl index 1a2db288..070ddd44 100644 --- a/src/DeepSplitting.jl +++ b/src/DeepSplitting.jl @@ -1,5 +1,6 @@ # import package using DifferentialEquations +using Flux Base.copy(t::Tuple) = t # required for below function Base.copy(opt::O) where O<:Flux.Optimise.AbstractOptimiser @@ -154,21 +155,35 @@ function solve( end - # calculating the SDE trajectories - use the SDESolver - function sde_loop!(y0,y1,dWall) + # calculating the SDE trajectories - use the SDESolver - it works + #function sde_loop!(y0,y1,dWall) + # x0_sample!(y1) #initial condition + # randn!(dWall) #points normally distributed for brownian motion + # for i in 1:size(dWall,3) + # t = ts[N + 1 - i] #this is dt + # dW = @view dWall[:,:,i] + # y0 .= y1 + # #y1 .= y0 .+ μ(y0,p,t) .* dt .+ σ(y0,p,t) .* sqrt(dt) .* dW + # prob = SDEProblem(y0 .+ μ(y0,p,t) .* dt,σ(y0,p,t) .* sqrt(dt),x0_sample!(y1),t) + # sol = solve(prob,EM(),dt=dt) + # if !isnothing(neumann_bc) + # y1 .= _reflect(y0, y1, neumann_bc[1], neumann_bc[2]) + # end + # end + #end + + # calculating the SDE trajectories - use the SDESolver + function sde_loop!(y0,y1,dWall) x0_sample!(y1) #initial condition randn!(dWall) #points normally distributed for brownian motion - for i in 1:size(dWall,3) - t = ts[N + 1 - i] #this is dt - dW = @view dWall[:,:,i] - y0 .= y1 - #y1 .= y0 .+ μ(y0,p,t) .* dt .+ σ(y0,p,t) .* sqrt(dt) .* dW - prob = SDEProblem(y0 .+ μ(y0,p,t) .* dt,σ(y0,p,t) .* sqrt(dt),x0_sample!(y1),t) - sol = solve(prob,EM(),dt=dt) - if !isnothing(neumann_bc) - y1 .= _reflect(y0, y1, neumann_bc[1], neumann_bc[2]) - end - end + y0 .= y1 + y1 .= y0 .+ μ(y0,p,t) .* dt .+ σ(y0,p,t) .* sqrt(dt) .* dW + prob = SDEProblem(y0 .+ μ(y0,p,t) .* dt,σ(y0,p,t) .* sqrt(dt),x0_sample!(y1),t) + ensembleprob = EnsembleProblem(prob) + sol = solve(ensembleprob, EnsembleSerial(), trajectories = 10) + if !isnothing(neumann_bc) + y1 .= _reflect(y0, y1, neumann_bc[1], neumann_bc[2]) + end end From 5d1638e5c73be88cbe700993766c06407476eabc Mon Sep 17 00:00:00 2001 From: Attilio Pittelli <70145737+leo-ai-for-trading@users.noreply.github.com> Date: Fri, 5 Apr 2024 13:13:00 +0200 Subject: [PATCH 04/10] Delete DeepSplitting.jl --- DeepSplitting.jl | 252 ----------------------------------------------- 1 file changed, 252 deletions(-) delete mode 100644 DeepSplitting.jl diff --git a/DeepSplitting.jl b/DeepSplitting.jl deleted file mode 100644 index 070ddd44..00000000 --- a/DeepSplitting.jl +++ /dev/null @@ -1,252 +0,0 @@ -# import package -using DifferentialEquations -using Flux - -Base.copy(t::Tuple) = t # required for below -function Base.copy(opt::O) where O<:Flux.Optimise.AbstractOptimiser - return O([copy(getfield(opt,f)) for f in fieldnames(typeof(opt))]...) -end - -""" - DeepSplitting(nn, K=1, opt = ADAM(0.01), λs = nothing, mc_sample = NoSampling()) - -Deep splitting algorithm. - -# Arguments -* `nn`: a [Flux.Chain](https://fluxml.ai/Flux.jl/stable/models/layers/#Flux.Chain), or more generally a [functor](https://github.com/FluxML/Functors.jl). -* `K`: the number of Monte Carlo integrations. -* `opt`: optimiser to be use. By default, `Flux.ADAM(0.01)`. -* `λs`: the learning rates, used sequentially. Defaults to a single value taken from `opt`. -* `mc_sample::MCSampling` : sampling method for Monte Carlo integrations of the non local term. Can be `UniformSampling(a,b)`, `NormalSampling(σ_sampling, shifted)`, or `NoSampling` (by default). - -# Example -```julia -hls = d + 50 # hidden layer size -d = 10 # size of the sample - -# Neural network used by the scheme -nn = Flux.Chain(Dense(d, hls, tanh), - Dense(hls,hls,tanh), - Dense(hls, 1, x->x^2)) - -alg = DeepSplitting(nn, K=10, opt = ADAM(), λs = [5e-3,1e-3], - mc_sample = UniformSampling(zeros(d), ones(d)) ) -``` -""" -struct DeepSplitting{NN,F,O,L,MCS} <: HighDimPDEAlgorithm - nn::NN - K::F - opt::O - λs::L - mc_sample!::MCS # Monte Carlo sample -end - -function DeepSplitting(nn; - K=1, - opt::O = ADAM(0.01), - λs::L = nothing, - mc_sample::MCSampling = NoSampling()) where {O <: Flux.Optimise.AbstractOptimiser, L <: Union{Nothing,Vector{N}} where N <: Number} - isnothing(λs) ? λs = [opt.eta] : nothing - DeepSplitting(nn, K, opt, λs, mc_sample) -end - -""" - solve(prob::PIDEProblem, - alg::DeepSplitting, - dt; - batch_size = 1, - abstol = 1f-6, - verbose = false, - maxiters = 300, - use_cuda = false, - cuda_device = nothing, - verbose_rate = 100) - -Returns a `PIDESolution` object. - -# Arguments -- `maxiters`: number of iterations per time step. Can be a tuple, where `maxiters[1]` is used for the training of the neural network used in the first time step (which can be long) and `maxiters[2]` is used for the rest of the time steps. -- `batch_size` : the batch size. -- `abstol` : threshold for the objective function under which the training is stopped. -- `verbose` : print training information. -- `verbose_rate` : rate for printing training information (every `verbose_rate` iterations). -- `use_cuda` : set to `true` to use CUDA. -- `cuda_device` : integer, to set the CUDA device used in the training, if `use_cuda == true`. -""" -function solve( - prob::PIDEProblem, - alg::DeepSplitting, - dt; - batch_size = 1, - abstol = 1f-6, - verbose = false, - maxiters = 300, - use_cuda = false, - cuda_device = nothing, - verbose_rate = 100 - ) - if use_cuda - if CUDA.functional() - @info "Training on CUDA GPU" - CUDA.allowscalar(false) - !isnothing(cuda_device) ? CUDA.device!(cuda_device) : nothing - _device = Flux.gpu - else - error("CUDA not functional, deactivate `use_cuda` and retry") - end - else - @info "Training on CPU" - _device = Flux.cpu - end - - ## unbin stuff - neumann_bc = prob.neumann_bc |> _device - x0 = prob.x |> _device - mc_sample! = alg.mc_sample! |> _device - x0_sample! = prob.x0_sample |> _device - - d = size(x0,1) - K = alg.K - opt = alg.opt - λs = alg.λs - g,f,μ,σ,p = prob.g,prob.f,prob.μ,prob.σ,prob.p - T = eltype(x0) - - # neural network model - nn = alg.nn |> _device - vi = g - # fix for deepcopy - vj = Flux.fmap(nn) do x - x isa AbstractArray && return copy(x) - x - end - ps = Flux.params(vj) - - dt = convert(T,dt) - ts = prob.tspan[1]:dt-eps(T):prob.tspan[2] - N = length(ts) - 1 - - usol = [g(x0 |>cpu)[]] - nns = Any[g] - losses = [Vector{eltype(prob.x)}() for net in 1:N+1] - - # allocating - x0_batch = repeat(x0, 1, batch_size) - y1 = similar(x0_batch) - y0 = similar(y1) - z = similar(x0, d, batch_size, K) # for MC non local integration - - # checking element types - eltype(mc_sample!) == T || !_integrate(mc_sample!) ? nothing : error( - "Element type of `mc_sample` not the same as element type of `x`") - - function splitting_model(y0, y1, z, t) - # TODO: for now hardcoded because of a bug in Zygote differentiation rules for adjoints - # vi_y1, ∇vi = Zygote.pullback(vi, y1) - # _int = reshape(sum(f(y1, z, vi_y1, vi(z), ∇vi(y1)[1], ∇vi(z)[1], p, t), dims = 3), 1, :) - ∇vi(x) = [0f0] - _int = reshape(sum(f(y1, z, vi(y1), vi(z), ∇vi(y1), ∇vi(z), p, t), dims = 3), 1, :) - return vj(y0) - (vi(y1) + dt * _int / K) - end - - function loss(y0, y1, z, t) - u = splitting_model(y0, y1, z, t) - return sum(u.^2) / batch_size - end - - - # calculating the SDE trajectories - use the SDESolver - it works - #function sde_loop!(y0,y1,dWall) - # x0_sample!(y1) #initial condition - # randn!(dWall) #points normally distributed for brownian motion - # for i in 1:size(dWall,3) - # t = ts[N + 1 - i] #this is dt - # dW = @view dWall[:,:,i] - # y0 .= y1 - # #y1 .= y0 .+ μ(y0,p,t) .* dt .+ σ(y0,p,t) .* sqrt(dt) .* dW - # prob = SDEProblem(y0 .+ μ(y0,p,t) .* dt,σ(y0,p,t) .* sqrt(dt),x0_sample!(y1),t) - # sol = solve(prob,EM(),dt=dt) - # if !isnothing(neumann_bc) - # y1 .= _reflect(y0, y1, neumann_bc[1], neumann_bc[2]) - # end - # end - #end - - # calculating the SDE trajectories - use the SDESolver - function sde_loop!(y0,y1,dWall) - x0_sample!(y1) #initial condition - randn!(dWall) #points normally distributed for brownian motion - y0 .= y1 - y1 .= y0 .+ μ(y0,p,t) .* dt .+ σ(y0,p,t) .* sqrt(dt) .* dW - prob = SDEProblem(y0 .+ μ(y0,p,t) .* dt,σ(y0,p,t) .* sqrt(dt),x0_sample!(y1),t) - ensembleprob = EnsembleProblem(prob) - sol = solve(ensembleprob, EnsembleSerial(), trajectories = 10) - if !isnothing(neumann_bc) - y1 .= _reflect(y0, y1, neumann_bc[1], neumann_bc[2]) - end - end - - - for net in 1:N - # preallocate dWall - dWall = similar(x0, d, batch_size, N + 1 - net) # for SDE - - verbose && println("Step $(net) / $(N) ") - t = ts[net] - # first of maxiters used for first nn, second used for the other nn - _maxiters = length(maxiters) > 1 ? maxiters[min(net,2)] : maxiters[] - - #modifying the sde_loop by replacing with StochasticDiffEq - for λ in λs - opt_net = copy(opt) # starting with a new optimiser state at each time step - opt_net.eta = λ - verbose && println("Training started with ", typeof(opt_net), " and λ :", opt_net.eta) - for epoch in 1:_maxiters - y1 .= x0_batch - # generating sdes - sde_loop!(y0, y1, dWall) - - if _integrate(mc_sample!) - # generating z for MC non local integration - mc_sample!(z, y1) - end - - # training - gs = Flux.gradient(ps) do - loss(y0, y1, z, t) - end - Flux.Optimise.update!(opt_net, ps, gs) # update parameters - - # report on training - if epoch % verbose_rate == 1 - l = loss(y0, y1, z, t) # explictly computing loss every verbose_rate - verbose && println("Current loss is: $l") - push!(losses[net], l) - if l < abstol - break - end - end - if epoch == maxiters - l = loss(y0, y1, z, t) - push!(losses[net+1], l) - verbose && println("Final loss for step $(net) / $(N) is: $l") - end - end - end - # saving - # fix for deepcopy - vi = Flux.fmap(vj) do x - x isa AbstractArray && return copy(x) - x - end - # vj = deepcopy(nn) - # ps = Flux.params(vj) - push!(usol, cpu(vi(reshape(x0, d, 1)))[]) - push!(nns, vi |> cpu) - end - - # return - sol = PIDESolution(x0, ts, losses, usol, nns) - return sol -end - From 43498733ca2cfbe54c244400d1810b880bab2a42 Mon Sep 17 00:00:00 2001 From: Attilio Pittelli <70145737+leo-ai-for-trading@users.noreply.github.com> Date: Fri, 5 Apr 2024 13:19:12 +0200 Subject: [PATCH 05/10] Update DeepSplitting.jl --- src/DeepSplitting.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DeepSplitting.jl b/src/DeepSplitting.jl index 070ddd44..c6055f90 100644 --- a/src/DeepSplitting.jl +++ b/src/DeepSplitting.jl @@ -180,7 +180,7 @@ function solve( y1 .= y0 .+ μ(y0,p,t) .* dt .+ σ(y0,p,t) .* sqrt(dt) .* dW prob = SDEProblem(y0 .+ μ(y0,p,t) .* dt,σ(y0,p,t) .* sqrt(dt),x0_sample!(y1),t) ensembleprob = EnsembleProblem(prob) - sol = solve(ensembleprob, EnsembleSerial(), trajectories = 10) + sol = solve(ensembleprob, EnsembleSerial(), trajectories = 3) if !isnothing(neumann_bc) y1 .= _reflect(y0, y1, neumann_bc[1], neumann_bc[2]) end From 2a8b27ff50fe29df00490ddd194bc90b658fb18d Mon Sep 17 00:00:00 2001 From: Attilio Pittelli <70145737+leo-ai-for-trading@users.noreply.github.com> Date: Fri, 5 Apr 2024 13:44:03 +0200 Subject: [PATCH 06/10] reduce number of trajectories --- src/DeepSplitting.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/DeepSplitting.jl b/src/DeepSplitting.jl index c6055f90..cc1ec20f 100644 --- a/src/DeepSplitting.jl +++ b/src/DeepSplitting.jl @@ -1,6 +1,6 @@ # import package -using DifferentialEquations -using Flux +#using DifferentialEquations +#using Flux Base.copy(t::Tuple) = t # required for below function Base.copy(opt::O) where O<:Flux.Optimise.AbstractOptimiser From 973b45cc29d44451d591659aacf4ddfa8d2be92e Mon Sep 17 00:00:00 2001 From: Attilio Pittelli <70145737+leo-ai-for-trading@users.noreply.github.com> Date: Fri, 5 Apr 2024 13:53:36 +0200 Subject: [PATCH 07/10] Update DeepSplitting.jl --- src/DeepSplitting.jl | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/DeepSplitting.jl b/src/DeepSplitting.jl index cc1ec20f..af4d4ddc 100644 --- a/src/DeepSplitting.jl +++ b/src/DeepSplitting.jl @@ -154,23 +154,6 @@ function solve( return sum(u.^2) / batch_size end - - # calculating the SDE trajectories - use the SDESolver - it works - #function sde_loop!(y0,y1,dWall) - # x0_sample!(y1) #initial condition - # randn!(dWall) #points normally distributed for brownian motion - # for i in 1:size(dWall,3) - # t = ts[N + 1 - i] #this is dt - # dW = @view dWall[:,:,i] - # y0 .= y1 - # #y1 .= y0 .+ μ(y0,p,t) .* dt .+ σ(y0,p,t) .* sqrt(dt) .* dW - # prob = SDEProblem(y0 .+ μ(y0,p,t) .* dt,σ(y0,p,t) .* sqrt(dt),x0_sample!(y1),t) - # sol = solve(prob,EM(),dt=dt) - # if !isnothing(neumann_bc) - # y1 .= _reflect(y0, y1, neumann_bc[1], neumann_bc[2]) - # end - # end - #end # calculating the SDE trajectories - use the SDESolver function sde_loop!(y0,y1,dWall) From 80048fd0f2a7827e6e05cb4321657adfe1b17f38 Mon Sep 17 00:00:00 2001 From: Attilio Pittelli <70145737+leo-ai-for-trading@users.noreply.github.com> Date: Fri, 5 Apr 2024 13:53:46 +0200 Subject: [PATCH 08/10] Update DeepSplitting.jl --- src/DeepSplitting.jl | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/DeepSplitting.jl b/src/DeepSplitting.jl index af4d4ddc..8add6dc4 100644 --- a/src/DeepSplitting.jl +++ b/src/DeepSplitting.jl @@ -1,6 +1,3 @@ -# import package -#using DifferentialEquations -#using Flux Base.copy(t::Tuple) = t # required for below function Base.copy(opt::O) where O<:Flux.Optimise.AbstractOptimiser From b4fc91b2bbe64eeaa1c9c0955264e0a00445d5e5 Mon Sep 17 00:00:00 2001 From: Attilio Pittelli <70145737+leo-ai-for-trading@users.noreply.github.com> Date: Fri, 5 Apr 2024 14:15:33 +0200 Subject: [PATCH 09/10] update t value --- src/DeepSplitting.jl | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/DeepSplitting.jl b/src/DeepSplitting.jl index 8add6dc4..dd8c4fc7 100644 --- a/src/DeepSplitting.jl +++ b/src/DeepSplitting.jl @@ -1,3 +1,6 @@ +# import package +#using DifferentialEquations +#using Flux Base.copy(t::Tuple) = t # required for below function Base.copy(opt::O) where O<:Flux.Optimise.AbstractOptimiser @@ -151,11 +154,29 @@ function solve( return sum(u.^2) / batch_size end + + # calculating the SDE trajectories - use the SDESolver - it works + #function sde_loop!(y0,y1,dWall) + # x0_sample!(y1) #initial condition + # randn!(dWall) #points normally distributed for brownian motion + # for i in 1:size(dWall,3) + # t = ts[N + 1 - i] #this is dt + # dW = @view dWall[:,:,i] + # y0 .= y1 + # #y1 .= y0 .+ μ(y0,p,t) .* dt .+ σ(y0,p,t) .* sqrt(dt) .* dW + # prob = SDEProblem(y0 .+ μ(y0,p,t) .* dt,σ(y0,p,t) .* sqrt(dt),x0_sample!(y1),t) + # sol = solve(prob,EM(),dt=dt) + # if !isnothing(neumann_bc) + # y1 .= _reflect(y0, y1, neumann_bc[1], neumann_bc[2]) + # end + # end + #end # calculating the SDE trajectories - use the SDESolver function sde_loop!(y0,y1,dWall) x0_sample!(y1) #initial condition randn!(dWall) #points normally distributed for brownian motion + t = ts[N::-1] #this is dt y0 .= y1 y1 .= y0 .+ μ(y0,p,t) .* dt .+ σ(y0,p,t) .* sqrt(dt) .* dW prob = SDEProblem(y0 .+ μ(y0,p,t) .* dt,σ(y0,p,t) .* sqrt(dt),x0_sample!(y1),t) From 00f05385440968699b76218f7b709a482030a33f Mon Sep 17 00:00:00 2001 From: Attilio Pittelli <70145737+leo-ai-for-trading@users.noreply.github.com> Date: Fri, 5 Apr 2024 14:26:51 +0200 Subject: [PATCH 10/10] Update t value --- src/DeepSplitting.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DeepSplitting.jl b/src/DeepSplitting.jl index dd8c4fc7..0a13be1c 100644 --- a/src/DeepSplitting.jl +++ b/src/DeepSplitting.jl @@ -176,7 +176,7 @@ function solve( function sde_loop!(y0,y1,dWall) x0_sample!(y1) #initial condition randn!(dWall) #points normally distributed for brownian motion - t = ts[N::-1] #this is dt + t = ts[N+1:-1:1] #this is dt y0 .= y1 y1 .= y0 .+ μ(y0,p,t) .* dt .+ σ(y0,p,t) .* sqrt(dt) .* dW prob = SDEProblem(y0 .+ μ(y0,p,t) .* dt,σ(y0,p,t) .* sqrt(dt),x0_sample!(y1),t)