DiffEqFlux.jl icon indicating copy to clipboard operation
DiffEqFlux.jl copied to clipboard

SingularException using collocate_data

Open bkuwahara opened this issue 4 years ago • 6 comments

Hi folks,

I've been trying to use the two-stage training method for collocation (as described in this example https://diffeqflux.sciml.ai/stable/examples/collocation/). I can run the example itself and it works great, but when I apply it to my own ODE I get this:

du,u = DiffEqFlux.collocate_data(data,tsteps)

SingularException(2)
in eval at base\boot.jl:360 
in top-level scope at nn_training.jl:218
in collocate_data at DiffEqFlux\GQl0U\src\collocation.jl:132
in collocate_data at DiffEqFlux\GQl0U\src\collocation.jl:142
in map at base\abstractarray.jl:2294 
in collect_similar at base\array.jl:606 
in _collect at base\array.jl:691
in iterate at base\generator.jl:47 
in  at DiffEqFlux\GQl0U\src\collocation.jl:149
in \ at stdlib\v1.6\LinearAlgebra\src\generic.jl:1128
in \ at stdlib\v1.6\LinearAlgebra\src\diagonal.jl:631
in ldiv! at stdlib\v1.6\LinearAlgebra\src\diagonal.jl:624

In trying to figure out whether it was some artifact of my data that was causing the problem, I found the same thing happening even with simple functions:

t = LinRange(0.0, 30.0, 100)
u = sin.(t)
du,u = DiffEqFlux.collocate_data(u',t)
# Same error

What's even more perplexing is that changing the timespan makes a difference:

t = LinRange(0.0, 15.0, 100)
u = sin.(t)
du,u = DiffEqFlux.collocate_data(u',t)
# SingularException(3) this time
t = LinRange(0.0, 18.0, 100)
u = sin.(t)
du,u = DiffEqFlux.collocate_data(u',t)
# Works

Kernel choice and presence/absence of noise don't seem to matter. I'm afraid I'm not familiar with the details of how the collocation method works, so I have no idea why the system would need to solve a singular matrix. Could someone enlighten me as to why this happens and how I can get this method to work consistently?

bkuwahara avatar Jun 07 '21 13:06 bkuwahara

It might require u to be a matrix?

ChrisRackauckas avatar Jun 07 '21 13:06 ChrisRackauckas

Still doesn't work, but for other reasons:

t = Array(LinRange(0.0, 18.0, 100))
t = reshape(t, 1,100)
x = sin.(t)
du,u = DiffEqFlux.collocate_data(x,t)
# ArgumentError: number of rows of each array must match (got (100, 1))

Taking the transpose of x makes no difference.

Edit: Tried again with a column vector instead of a row vector.

t = Array(LinRange(0.0, 18.0, 100))
t = reshape(t, 100,1)
x = sin.(t)
du,u = DiffEqFlux.collocate_data(x,t)

This time it gives SingularException(1)

bkuwahara avatar Jun 07 '21 14:06 bkuwahara

Hey! Did you manage to get this right? I'm facing the same problem. Always throwing singular expection even with large noise.

viniviena avatar Jun 22 '22 16:06 viniviena

Yes, I am still getting the error even on the latest version of DiffEqFlux.

bkuwahara avatar Jun 23 '22 14:06 bkuwahara

I figured out how to solve it for my case. It turns out that inserting data with too distinct scales and with slow dynamics causes exception. In my case, "t" (independent variable) was between 0 and 3000 and y (dependent) between 0 and 0.5. It caused the derivatives to be too small as delta_t is too large compared to delta_y. I first divided t by 3000 and used the collocate_data(), then divided the calculated derivative by 3000 (to have the correct order of magnitude back).

viniviena avatar Jun 23 '22 16:06 viniviena

Yes I think that is probably the right way to go.

ChrisRackauckas avatar Jun 24 '22 01:06 ChrisRackauckas

The re-scaling is done on the latest versions.

ChrisRackauckas avatar Nov 22 '23 16:11 ChrisRackauckas