Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

InexactError when optimizing Complex-valued function #127

Open
ssfrr opened this issue Sep 24, 2019 · 4 comments
Open

InexactError when optimizing Complex-valued function #127

ssfrr opened this issue Sep 24, 2019 · 4 comments

Comments

@ssfrr
Copy link

ssfrr commented Sep 24, 2019

I'm trying to optimize a real-valued parameter to minimize a complex-valued least-squares problem.

Here's a MWE that demonstrates the problem. The basic idea is that you have a signal (x) and a delayed version of that signal (x2), and the object is to estimate the delay. We perform the delay in the frequency domain so that we can handle fractional-sample delays.

So the delay D is what we're trying to optimize for, and the objective function is the least-squares difference (sum(abs2.(X2 - model(X)))) in the spectra.

D_true = 1.35
x = [0; 1; zeros(14)]
X = rfft(x)
ω = range(0, π, length=9)

# delay x in the frequency domain
X2 = X .* exp.(-im * D_true .* ω)
x2 = irfft(X2, length(x))

function model(Xs, D)
    X = @view Xs[:, 1]
    ω = @view Xs[:, 2]
    X .* exp.(-im * D[1] .* ω)
end

fit = curve_fit(model, [X ω], X2, [1.5])

Running curve_fit gives an InexactError - it looks like it's trying to assign a complex value into a real-valued array.

@Magalame
Copy link
Contributor

Magalame commented Nov 30, 2019

The reason for this is that in levenberg_marquardt.jl we require the value of the jacobian of the function-to-be-fitted. To compute it, we rely on OnceDifferentiable from NLSolversBase.jl. When the jacobian isn't given by the user, OnceDifferentiable will rely on finite_difference_jacobian! from DiffEqTools. In this case it complains because the type of p0 differs from the type of [X ω] and X2.

If you try fit = curve_fit(model, [X ω], X2, [1.5+0im]), you'll see that this error disappears, but...an another one comes up:

MethodError: no method matching OptimBase.MultivariateOptimizationResults(::LsqFit.LevenbergMarquardt, ::Array{Complex{Float64},1}, ::Array{Complex{Float64},1}, ::Float64, ::Int64, ::Bool, ::Bool, ::Float64, ::Float64, ::Bool, ::Float64, ::Float64, ::Bool, ::Float64, ::Float64, ::Bool, ::Array{OptimBase.OptimizationState{LsqFit.LevenbergMarquardt},1}, ::Int64, ::Int64, ::Int64)

Now, MultivariateOptimizationResults is a struct from OptimBase.jl that LsqFit.jluses to store its results. Here it is complaining that the variables (so the parameters you want to optimize) have a different type (Complex{Float64}) than the type of the sum of residuals (Float64).

In order words, you should rather open a ticket in OptimBase.jl :)

@pkofod
Copy link
Member

pkofod commented Jan 2, 2020

Thanks for the example. I'll keep it in mind when changing "optimization backend" in the near future.

@dominikkiese
Copy link

Have there been any changes to allow for complex valued data to be used within curve_fit? I am currently running into the same problem as OP, but have not found a way around it so far.

@mzaffalon
Copy link
Contributor

A quick look at the literature reveals that the Levenberg-Marquardt is only defined for real-valued functions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants