Reputation: 13
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
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
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