# Least square with multi-value function

**URL:** https://discourse.julialang.org/t/least-square-with-multi-value-function/47943
**Category:** Optimization (Mathematical)
**Tags:** curve-fitting
**Created:** [October 7, 2020, 4:01pm UTC](https://discourse.julialang.org/t/least-square-with-multi-value-function/47943 "2020-10-07T16:01:49Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![Bernard\_GODARD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bernard_godard/32/4155_2.png) [@Bernard\_GODARD](https://discourse.julialang.org/u/Bernard_GODARD)
#### Post date: [October 7, 2020, 4:01pm UTC](https://discourse.julialang.org/t/least-square-with-multi-value-function/47943/1 "2020-10-07T16:01:49Z")

</div>

I have a model which takes 3 independent variables, 4 parameters and returns 2 values.  
I am trying to fit the parameters to a certain dataset.

LsqFit does not seem to like multivalues function but maybe I am not using it correctly:

```julia
using CSV

data = CSV.read("panel.csv")
N = size(data)[1]

function fitmodel(x,p)
    r =@view x[:,1]
    T1 =@view x[:,2]
    θ =@view x[:,3]
    α1,α2,k,T2 = p

    vcat( α1.*T1.^4 .+ k.*(T1.-T2) .- cosd.(θ)./r.^2 , α2.*T2^4 .+ k .* (T2.-T1) )
end

x = convert(Matrix,data[:,[:Distance,:Temp,:Tilt]])
y = zeros(2*N)

# initial guess
r, T1, θ = x[end,:]
α1 = (cosd(θ)/r^2)/T1^4
α2 = α1
dT = 10.0
T2 = T1 - dT
k = α2*T2^4 / dT
p0 = [α1 α2 k T2]

println("Initial guess: ",p0)

using LsqFit
fit = curve_fit(fitmodel, x, y, p0)

```

I get the following error:

```julia
ERROR: MethodError: no method matching levenberg_marquardt(::NLSolversBase.OnceDifferentiable{Array{Float64,1},Array{Float64,2},Array{Float64,2}}, ::Array{Float64,2})

You might have used a 2d row vector where a 1d column vector was required.
Note the difference between 1d column vector [1,2,3] and 2d row vector [1 2 3].
You can convert to a column vector with the vec() function.
Closest candidates are:
  levenberg_marquardt(::NLSolversBase.OnceDifferentiable, ::AbstractArray{T,1}; x_tol, g_tol, maxIter, lambda, tau, lambda_increase, lambda_decrease, min_step_quality, good_step_quality, show_trace, lower, upper, avv!) where T at /home/bgodard/.julia/packages/LsqFit/LeVh7/src/levenberg_marquardt.jl:34
Stacktrace:
 [1] lmfit(::NLSolversBase.OnceDifferentiable{Array{Float64,1},Array{Float64,2},Array{Float64,2}}, ::Array{Float64,2}, ::Array{Float64,1}; autodiff::Symbol, kwargs::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at /home/bgodard/.julia/packages/LsqFit/LeVh7/src/curve_fit.jl:68
 [2] lmfit(::NLSolversBase.OnceDifferentiable{Array{Float64,1},Array{Float64,2},Array{Float64,2}}, ::Array{Float64,2}, ::Array{Float64,1}) at /home/bgodard/.julia/packages/LsqFit/LeVh7/src/curve_fit.jl:68
 [3] lmfit(::LsqFit.var"#18#20"{typeof(fitmodel),Array{Float64,2},Array{Float64,1}}, ::Array{Float64,2}, ::Array{Float64,1}; autodiff::Symbol, kwargs::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at /home/bgodard/.julia/packages/LsqFit/LeVh7/src/curve_fit.jl:64
 [4] lmfit(::Function, ::Array{Float64,2}, ::Array{Float64,1}) at /home/bgodard/.julia/packages/LsqFit/LeVh7/src/curve_fit.jl:61
 [5] curve_fit(::typeof(fitmodel), ::Array{Float64,2}, ::Array{Float64,1}, ::Array{Float64,2}; inplace::Bool, kwargs::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at /home/bgodard/.julia/packages/LsqFit/LeVh7/src/curve_fit.jl:115
 [6] curve_fit(::Function, ::Array{Float64,2}, ::Array{Float64,1}, ::Array{Float64,2}) at /home/bgodard/.julia/packages/LsqFit/LeVh7/src/curve_fit.jl:106

```

Both the model and observation are column vectors but obviously I need to have the observation and modeled vectors twice as long as the input data.

I have also tried an observation matrix with:

```julia
y = zeros(N,2)

```

and using hcat instead of vcat in the model return value, but this results in the same error.

Here I am targeting (0,0) for the observation so I could create a univalue function returning the vector norm but this would not be numerically optimal. Another solution would be to duplicate the data vector entries and add a discrete independent variable to switch between the 2 components of the function but this looks convoluted.

What is the easiest way with the Julia ecosystem to fit a multi-value function?

---

<div class="post-metadata">

### Author: ![Bernard\_GODARD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bernard_godard/32/4155_2.png) [@Bernard\_GODARD](https://discourse.julialang.org/u/Bernard_GODARD)
#### Post date: [October 9, 2020, 5:39am UTC](https://discourse.julialang.org/t/least-square-with-multi-value-function/47943/2 "2020-10-09T05:39:27Z")

</div>

I found the problem. The initial parameter vector was a row. It needs to be a column:

```julia
p0 = [α1, α2, k, T2]

```

---

<div class="post-metadata">

### Author: ![Stephen](https://avatars.discourse-cdn.com/v4/letter/s/96bed5/32.png) [@Stephen](https://discourse.julialang.org/u/Stephen)
#### Post date: [March 28, 2024, 2:54am UTC](https://discourse.julialang.org/t/least-square-with-multi-value-function/47943/3 "2024-03-28T02:54:20Z")

</div>

```julia
using XLSX, DataFrames, LsqFit

df = DataFrame(XLSX.readtable("SMB.xlsx","平衡吸附量", infer_eltypes = true))

function Com_Langmuir(p, x)
    Ha, bA, bC, Hc = p
    CA = @view x[:, 1]
    CC = @view x[:, 2]
    @. qA = Ha*CA / (1 + bA*CA + bC*CC)
    @. qC = Hc*CC / (1 + bA*CA + bC*CC)
    vcat(qA, qC) #返回一个列向量
end

xdata = [df.CA df.CC]

ydata = vcat(df.qA_303K, df.qC_303K)

p0 = [1.983, 0.0067, 0.1951, 1.61]

ret = curve_fit(Com_Langmuir, xdata, ydata, p0)

```

which throws error as:

```julia
ERROR: BoundsError: attempt to access 4-element Vector{Float64} at index [1:4, 2]
Stacktrace:
  [1] throw_boundserror(A::Vector{Float64}, I::Tuple{Base.Slice{Base.OneTo{Int64}}, Int64}) @ Base .\abstractarray.jl:737
  [2] checkbounds
    @ .\abstractarray.jl:702 [inlined]
  [3] view
    @ .\subarray.jl:184 [inlined]
  [4] Com_Langmuir(p::Matrix{Float64}, x::Vector{Float64})
    @ Main e:\06325\Julialang\test.jl:21
  [5] (::LsqFit.var"#18#20"{typeof(Com_Langmuir), Matrix{Float64}, Vector{Float64}})(p::Vector{Float64})
    @ LsqFit C:\Users\admin\.julia\packages\LsqFit\OglWj\src\curve_fit.jl:139
  [6] lmfit(f::LsqFit.var"#18#20"{…}, p0::Vector{…}, wt::Vector{…}; autodiff::Symbol, kwargs::@Kwargs{})
    @ LsqFit C:\Users\admin\.julia\packages\LsqFit\OglWj\src\curve_fit.jl:69
  [7] lmfit
    @ C:\Users\admin\.julia\packages\LsqFit\OglWj\src\curve_fit.jl:54 [inlined]
  [8] curve_fit(model::typeof(Com_Langmuir), xdata::Matrix{…}, ydata::Vector{…}, p0::Vector{…}; inplace::Bool, kwargs::@Kwargs{})
    @ LsqFit C:\Users\admin\.julia\packages\LsqFit\OglWj\src\curve_fit.jl:140
  [9] curve_fit(model::Function, xdata::Matrix{Float64}, ydata::Vector{Float64}, p0::Vector{Float64})
    @ LsqFit C:\Users\admin\.julia\packages\LsqFit\OglWj\src\curve_fit.jl:123
 [10] top-level scope
    @ e:\06325\Julialang\test.jl:33
Some type information was truncated. Use `show(err)` to see complete types.

```

---

<div class="post-metadata">

### Author: ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)
#### Post date: [March 28, 2024, 4:33am UTC](https://discourse.julialang.org/t/least-square-with-multi-value-function/47943/4 "2024-03-28T04:33:46Z")

</div>

Hi @Stephen,

The problem is that `x` is a vector in `Com_Langmuir`.

The line `CC = @view x[:, 2]` is trying to access the second column of `x`, which doesn’t exist.

p.s., If you have more questions, please start a new thread and provide a reproducible example, instead of replying here.
