I am attempting to “solve” the issue (for now on dummy data) by creating a multi-branch neural network, where one branch predicts a and b based on soil, precipitation (at time t, t-1, etc) and an other branch carry on with the volumes across the network. Finally, a terminal layer embeds the structure that I want to maintain (logistic in relation to the current volume) working on a function of (a, b and v0)
This avoids me to estimate separately a and b that are unobserved.
This is the code on dummy data:
using BetaML, Plots
# Dummy data creation....
N = 4000
x = rand(1:0.001:2,N,5)
e = rand(N)/1000
a = @. x[:,1]^2 - 2 * x[:,2]^2 + 3 * x[:,3]^2 - 4 * x[:,4]^1 + 2 * x[:,5] + e + 10
b = @. (2 *x[:,1]^2 + 4 * x[:,2]^2 + 5 * x[:,3] + 4 * x[:,4]^1 + 2 * x[:,5] + e *10) *100
v0 = rand(17:0.001:22,N)
xv = hcat(x,v0)
dv = @. a * v0 - (a/b) * v0^2
# Method 1: direct estimation of dv...
layers = [DenseLayer(6,10,f=relu),
DenseLayer(10,10,f=relu),
DenseLayer(10,1,f=identity)]
m = NeuralNetworkEstimator(epochs=200, batch_size=4, layers=layers)
dv_est = fit!(m, xv, dv)
hcat(dv,dv_est)
mse(dv,dv_est) # 51.61
# Method 2: Structure estimation...
# I create a NN with a branch for the parameters a and b, and a separate branch for the volume, and then Icreate a (weightless) function layer that computes the growth based on the two parameters and the current volume.
dvcomp(x) = [x[1] * x[3] - (x[1] / x[2]) * x[3]^2] # x is [a ,b, V] - output must be a vector
l1_ab = DenseLayer(5,10,f=relu)
l1_v = ReplicatorLayer(1)
l1 = GroupedLayer([l1_ab,l1_v])
l2_ab = DenseLayer(10,10,f=relu)
l2_v = ReplicatorLayer(1)
l2 = GroupedLayer([l2_ab,l2_v])
l3_ab = DenseLayer(10,2,f=identity)
l3_v = ReplicatorLayer(1)
l3 = GroupedLayer([l3_ab,l3_v])
l4 = VectorFunctionLayer(3,f=dvcomp)
layers=[l1,l2,l3,l4]
m = NeuralNetworkEstimator(epochs=200, batch_size=4, layers=layers)
dv_est = fit!(m, xv, dv)
hcat(dv,dv_est)
mse(dv,dv_est) # 5.23
plot(dv,dv_est, label=nothing,xlabel="obs",ylabel="est")
The predictions (on dummy data) seems very good:
However, I may be doing something very dummy, as the model seems not respected.. going to look on this..