Julia 使用 LsqFit 进行洛伦兹曲线拟合
Julia using LsqFit for Lorentzian curve fitting
Julia 中的以下代码绘制了一条洛伦兹曲线,然后使用 curve_fit 函数来确定参数。
using LsqFit
model(x,p)=p[1] ./(p[1]^2 .+(x .-p[2]).^2)
#Test values
p0=[10,50]
tdata=range(-150,stop=150,length=300)
ydata = model(tdata, p0)
fit=curve_fit(model,tdata,ydata,p0)
在这种情况下,结果应该是准确的,因为我使用模型计算 y 值,然后将这些准确的 y 值传递给 curve_fit 函数。但是,Julia returns 错误:
InexactError: Int64(NaN)
Int64(::Float64) at float.jl:710
x_of_nans(::Array{Int64,1}, ::Type{T} where T) at NLSolversBase.jl:60
x_of_nans(::Array{Int64,1}) at NLSolversBase.jl:60
NLSolversBase.OnceDifferentiable(::Function, ::Function, ::Function, ::Array{Int64,1}, ::Array{Float64,1}, ::Array{Float64,2}; inplace::Bool) at oncedifferentiable.jl:229
NLSolversBase.OnceDifferentiable(::Function, ::Function, ::Function, ::Array{Int64,1}, ::Array{Float64,1}, ::Array{Float64,2}) at oncedifferentiable.jl:225
NLSolversBase.OnceDifferentiable(::NLSolversBase.var"#ff!#1"{LsqFit.var"#18#20"{typeof(model),StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}},Array{Float64,1}}}, ::Array{Int64,1}, ::Array{Float64,1}, ::Array{Float64,2}, ::Symbol, ::ForwardDiff.Chunk{2}) at oncedifferentiable.jl:147
NLSolversBase.OnceDifferentiable(::Function, ::Array{Int64,1}, ::Array{Float64,1}, ::Array{Float64,2}, ::Symbol) at oncedifferentiable.jl:96
NLSolversBase.OnceDifferentiable(::Function, ::Array{Int64,1}, ::Array{Float64,1}, ::Array{Float64,2}; inplace::Bool, autodiff::Symbol) at oncedifferentiable.jl:28
(::Core.var"#Type##kw")(::NamedTuple{(:inplace, :autodiff),Tuple{Bool,Symbol}}, ::Type{NLSolversBase.OnceDifferentiable}, ::Function, ::Array{Int64,1}, ::Array{Float64,1}, ::Array{Float64,2}) at oncedifferentiable.jl:26
(::Core.var"#Type##kw")(::NamedTuple{(:inplace, :autodiff),Tuple{Bool,Symbol}}, ::Type{NLSolversBase.OnceDifferentiable}, ::Function, ::Array{Int64,1}, ::Array{Float64,1}) at oncedifferentiable.jl:26
lmfit(::LsqFit.var"#18#20"{typeof(model),StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}},Array{Float64,1}}, ::Array{Int64,1}, ::Array{Float64,1}; autodiff::Symbol, kwargs::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at curve_fit.jl:63
lmfit(::Function, ::Array{Int64,1}, ::Array{Float64,1}) at curve_fit.jl:61
curve_fit(::typeof(model), ::StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}}, ::Array{Float64,1}, ::Array{Int64,1}; inplace::Bool, kwargs::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at curve_fit.jl:115
curve_fit(::Function, ::StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}}, ::Array{Float64,1}, ::Array{Int64,1}) at curve_fit.jl:106
top-level scope at mcconnel_simulation.jl:71
为什么curve_fit无法解决这个简单的问题?
p0
需要有 float eltype
(例如 Float64
):
julia> p0=[10.0,50.0]
2-element Array{Float64,1}:
10.0
50.0
julia> fit=curve_fit(model,collect(tdata),ydata,p0)
LsqFit.LsqFitResult{Array{Float64,1},Array{Float64,1},Array{Float64,2},Array{Float64,1}}([10.0, 50.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 … -2.168404344971009e-19, -6.505213034913027e-19, 2.168404344971009e-19, 4.336808689942018e-19, 2.168404344971009e-19, 2.168404344971009e-19, 0.0, 0.0, 0.0, 0.0], [2.4813278524001437e-5 -2.4875467192362816e-6; 2.506222852629442e-5 -2.52523618286487e-6; … ; 9.896618565083517e-5 2.0199959191107846e-5; 9.704930889082663e-5 1.9605920988595578e-5], true, Float64[])
你也可以写p0 = Float64[10,50]
来确保它的eltype
是Float64
。
Julia 中的以下代码绘制了一条洛伦兹曲线,然后使用 curve_fit 函数来确定参数。
using LsqFit
model(x,p)=p[1] ./(p[1]^2 .+(x .-p[2]).^2)
#Test values
p0=[10,50]
tdata=range(-150,stop=150,length=300)
ydata = model(tdata, p0)
fit=curve_fit(model,tdata,ydata,p0)
在这种情况下,结果应该是准确的,因为我使用模型计算 y 值,然后将这些准确的 y 值传递给 curve_fit 函数。但是,Julia returns 错误:
InexactError: Int64(NaN)
Int64(::Float64) at float.jl:710
x_of_nans(::Array{Int64,1}, ::Type{T} where T) at NLSolversBase.jl:60
x_of_nans(::Array{Int64,1}) at NLSolversBase.jl:60
NLSolversBase.OnceDifferentiable(::Function, ::Function, ::Function, ::Array{Int64,1}, ::Array{Float64,1}, ::Array{Float64,2}; inplace::Bool) at oncedifferentiable.jl:229
NLSolversBase.OnceDifferentiable(::Function, ::Function, ::Function, ::Array{Int64,1}, ::Array{Float64,1}, ::Array{Float64,2}) at oncedifferentiable.jl:225
NLSolversBase.OnceDifferentiable(::NLSolversBase.var"#ff!#1"{LsqFit.var"#18#20"{typeof(model),StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}},Array{Float64,1}}}, ::Array{Int64,1}, ::Array{Float64,1}, ::Array{Float64,2}, ::Symbol, ::ForwardDiff.Chunk{2}) at oncedifferentiable.jl:147
NLSolversBase.OnceDifferentiable(::Function, ::Array{Int64,1}, ::Array{Float64,1}, ::Array{Float64,2}, ::Symbol) at oncedifferentiable.jl:96
NLSolversBase.OnceDifferentiable(::Function, ::Array{Int64,1}, ::Array{Float64,1}, ::Array{Float64,2}; inplace::Bool, autodiff::Symbol) at oncedifferentiable.jl:28
(::Core.var"#Type##kw")(::NamedTuple{(:inplace, :autodiff),Tuple{Bool,Symbol}}, ::Type{NLSolversBase.OnceDifferentiable}, ::Function, ::Array{Int64,1}, ::Array{Float64,1}, ::Array{Float64,2}) at oncedifferentiable.jl:26
(::Core.var"#Type##kw")(::NamedTuple{(:inplace, :autodiff),Tuple{Bool,Symbol}}, ::Type{NLSolversBase.OnceDifferentiable}, ::Function, ::Array{Int64,1}, ::Array{Float64,1}) at oncedifferentiable.jl:26
lmfit(::LsqFit.var"#18#20"{typeof(model),StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}},Array{Float64,1}}, ::Array{Int64,1}, ::Array{Float64,1}; autodiff::Symbol, kwargs::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at curve_fit.jl:63
lmfit(::Function, ::Array{Int64,1}, ::Array{Float64,1}) at curve_fit.jl:61
curve_fit(::typeof(model), ::StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}}, ::Array{Float64,1}, ::Array{Int64,1}; inplace::Bool, kwargs::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at curve_fit.jl:115
curve_fit(::Function, ::StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}}, ::Array{Float64,1}, ::Array{Int64,1}) at curve_fit.jl:106
top-level scope at mcconnel_simulation.jl:71
为什么curve_fit无法解决这个简单的问题?
p0
需要有 float eltype
(例如 Float64
):
julia> p0=[10.0,50.0]
2-element Array{Float64,1}:
10.0
50.0
julia> fit=curve_fit(model,collect(tdata),ydata,p0)
LsqFit.LsqFitResult{Array{Float64,1},Array{Float64,1},Array{Float64,2},Array{Float64,1}}([10.0, 50.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 … -2.168404344971009e-19, -6.505213034913027e-19, 2.168404344971009e-19, 4.336808689942018e-19, 2.168404344971009e-19, 2.168404344971009e-19, 0.0, 0.0, 0.0, 0.0], [2.4813278524001437e-5 -2.4875467192362816e-6; 2.506222852629442e-5 -2.52523618286487e-6; … ; 9.896618565083517e-5 2.0199959191107846e-5; 9.704930889082663e-5 1.9605920988595578e-5], true, Float64[])
你也可以写p0 = Float64[10,50]
来确保它的eltype
是Float64
。