Question: Least square fitting method for non-linear function

To fit the non-linear function with other data, I am trying to use the ‘LsqFit.curve_fit’ which was introduced by the following link: GitHub - JuliaNLSolvers/LsqFit.jl: Simple curve fitting in Julia

here is toy example:

using DelimitedFiles, Plots, Serialization, Transducers, Match, LsqFit, Dierckx
        #meta=deserialize("meta_SPS.bin");
	 meta=rand(55,27,150) #same type with real meta
        #Fv_NOC=deserialize("Fv_NOC.bin");
	 Fv_NOC=rand(200,3,55) #same type with real meta
        meta_start=395; meta_end=400; meta_div=trunc(Int,((meta_end-meta_start)*100)); #
        meta_cal=LinRange(meta_start,meta_end,meta_div);
            I_sharp=Array{Float64,2}(undef,150,27);
            I_broad=zeros(Float64, meta_div)
            obs_metaq=LinRange(394,402,205); obs_Iq=LinRange(100,1000,205);
            function OTrans(meta, meta_shift, Holn, Fv_NOC, p)
                Translation=p
                for brazera=1:27;
                    for J1=1:150
                        I_sharp[J1,brazera]=(1/(meta[J1,brazera,numb_v].-meta_shift[numb_v])^4)*Holn[J1,brazera]*exp(-2.2/Translation)
                        I_broad.+= I_sharp[J1,brazera].*exp.(-2 .*( meta_cal .-(meta[J1,brazera,numb_v])).^2)
                    end 
                end
                return I_broad
            end
            interpolation=Spline1D(obs_metaq, obs_Iq, k=1)
            Int_Iq=interpolation(meta_cal) #Finding query points
            p0=Float64.([300])
            fit=LsqFit.curve_fit(OTrans,meta_cal,Int_Iq,p0)

I made a code similar to the example introduced, but it didn’t work leaving an error like the following message:

ERROR: MethodError: no method matching OTrans(::LinRange{Float64, Int64}, ::Vector{Float64})
Closest candidates are:
  OTrans(::Any) at Toy_example.jl:48
Stacktrace:
 [1] (::LsqFit.var"#18#20"{typeof(OTrans), LinRange{Float64, Int64}, Vector{Float64}})(p::Vector{Float64})

How can I get this to work? or any other method?

It looks like LsqFit.curve_fit expects the model function you want to minimize as first argument, but the arguments of this model function have to have a specific signature.

In your example, OTrans requires five arguments, but the model function has to accept two arguments with a specific meaning. This is documented here

If you want to keep your OTrans function as it is, one possibility would be to define another function with the right signature that internally calls OTrans in the right way. Something like

OTrans(#= different arguments here =#) = ...
model(x, p) = OTrans(#= use x, p to compute the right arguments for OTrans =#)

Aside: Your code is formatted in a pretty weird way which makes it hard to see what is going on. To make it easier for yourself and others, you might want to format the code a bit (e.g. put statements in the same scope at the same indentation level).

1 Like

As follow your comment, I put an argument as an array having 4 elements.
But it doesn’t work with the error as follows: MethodError: no method matching isinf(::Array{Float64, 3}).
Cite: How to use the array as the argument for curve-fit?
Is there a way to solve this problem?

other posts I cited: