user14951148
user14951148

Reputation: 13

Optimization in Julia with Optim.jl - How do I get rid of this error?

newbie here

I'm trying to minimize a function in Julia with optim.jl. The function works, but when I try to optimize it it gives me this error message:

MethodError: no method matching -(::Float64, ::Array{Float64,1})
For element-wise subtraction, use broadcasting with dot syntax: scalar .- array
Closest candidates are:
  -(::Float64, !Matched::Float64) at float.jl:403
  -(::Float64) at float.jl:393
  -(::Real, !Matched::Complex{Bool}) at complex.jl:302
  ...

Stacktrace:
 [1] _broadcast_getindex_evalf at ./broadcast.jl:648 [inlined]
 [2] _broadcast_getindex at ./broadcast.jl:621 [inlined]
 [3] getindex at ./broadcast.jl:575 [inlined]
 [4] copy at ./broadcast.jl:876 [inlined]
 [5] materialize at ./broadcast.jl:837 [inlined]
 [6] broadcast_preserving_zero_d at ./broadcast.jl:826 [inlined]
 [7] -(::Array{Float64,1}, ::Array{Array{Float64,1},1}) at ./arraymath.jl:39
 [8] objective(::Array{Float64,1}) at ./In[147]:4
 [9] value!!(::NonDifferentiable{Float64,Array{Float64,1}}, ::Array{Float64,1}) at /ext/julia/depot/packages/NLSolversBase/NsXIC/src/interface.jl:9
 [10] initial_state(::NelderMead{Optim.AffineSimplexer,Optim.AdaptiveParameters}, ::Optim.Options{Float64,Nothing}, ::NonDifferentiable{Float64,Array{Float64,1}}, ::Array{Float64,1}) at /ext/julia/depot/packages/Optim/TNmSw/src/multivariate/solvers/zeroth_order/nelder_mead.jl:158
 [11] optimize(::NonDifferentiable{Float64,Array{Float64,1}}, ::Array{Float64,1}, ::NelderMead{Optim.AffineSimplexer,Optim.AdaptiveParameters}, ::Optim.Options{Float64,Nothing}) at /ext/julia/depot/packages/Optim/TNmSw/src/multivariate/optimize/optimize.jl:33
 [12] optimize(::Function, ::Array{Float64,1}; inplace::Bool, autodiff::Symbol, kwargs::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at /ext/julia/depot/packages/Optim/TNmSw/src/multivariate/optimize/interface.jl:64
 [13] optimize(::Function, ::Array{Float64,1}) at /ext/julia/depot/packages/Optim/TNmSw/src/multivariate/optimize/interface.jl:58
 [14] top-level scope at In[148]:3
 [15] include_string(::Function, ::Module, ::String, ::String) at ./loading.jl:1091

This is my code:

function objective(b)
    x = x1[:,2]
    b = fill(b,T)
    u = y - x.*b
    obj = sum(u.^2)
    return obj
end

using Optim

Sol = optimize(objective,[0.0;0.0])
b_optim = Optim.minimizer(Sol)

, where x and y are Array{Float64,1}

I don't understand this error message. If I understand it correctly, it tells me that I'm trying to subtract an array from a number, which I'm not doing?! Broadcasting also doesn't work.

Upvotes: 1

Views: 1324

Answers (2)

Oskar
Oskar

Reputation: 1460

You should add arguments to your function, so that you can be sure you're passing the right variables. Then you should not use fill(b,T) as it allocates a new array uselessly. Furthermore, if you have an univariate problem you should give to the solver only one variable and as written in the documentation (Optim.jl/stable/#user/minimization/) you should use another solver, like LBFGS().

Summing up this would look like:

using Optim
function objective(b, x1, y)
    x = x1[:,2]
    u = y - x.*b
    obj = sum(u.^2)
    return obj
end

x1 = rand(10,10)
y = rand(10)
Sol = optimize(b -> objective(b,x1,y),[0.0], LBFGS())
b_optim = Optim.minimizer(Sol)

Upvotes: 2

Przemyslaw Szufel
Przemyslaw Szufel

Reputation: 42214

You can replicate your error via:

julia> 4 - [2,5]
ERROR: MethodError: no method matching -(::Int64, ::Array{Int64,1})

That it means is that your y is not a vector as expected but a scalar.

One possible way to address the issue is to broadcast -:

julia> 4 .- [2,5]
2-element Array{Int64,1}:
  2
 -1

Another problem with your code already mentioned in comments are global variables. You should never do that due to type stability and performance. For sure now it is the time to read: https://docs.julialang.org/en/v1/manual/performance-tips/

Upvotes: 0

Related Questions