【问题标题】:Optimization in Julia with Optim.jl - How do I get rid of this error?使用 Optim.jl 在 Julia 中进行优化 - 如何消除此错误?
【发布时间】:2021-01-06 10:58:17
【问题描述】:

这里是新手

我正在尝试使用 optim.jl 最小化 Julia 中的一个函数。该功能有效,但是当我尝试对其进行优化时,它给了我以下错误消息:

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

这是我的代码:

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)

,其中 x 和 y 是 Array{Float64,1}

我不明白这个错误信息。如果我理解正确,它会告诉我我正在尝试从一个数字中减去一个数组,而我没有这样做?!广播也不起作用。

【问题讨论】:

  • 您没有在函数内定义x1y,因此函数从一般范围内获取这两个变量的值。我猜这与你所说的相反,yFloat64 而不是数组。
  • 顺便说一句,T 在你的函数中也没有定义。您应该将变量作为参数传递或在函数中定义它们。
  • 感谢您的回复!我有更多的代码并定义了上面的所有内容,但我不想展示整个事情。 x1、y 和 T 不会改变,所以我没有将它们包含在公式中。所以你是说他们都必须在函数中才能工作? (即函数目标(x1,y,b,T)?
  • 不,如果它们在一般范围内,它也可以工作,但这样做不是一个好习惯,因为您无法确定它们的真正含义,并且 JIT 无法优化该功能编译器。我会将它们作为参数传递,这样您就不会出错,并且为了调试,您可以尝试在您的函数中编写 println(y),以便您了解它的真正含义。
  • 谢谢,我会努力的。我打印了 y,它是一个列向量 (Array{Float64,1})。丁字裤是该函数在我运行时不会返回错误消息,但优化中使用的函数会返回,所以我认为错误必须在某个地方的优化部分

标签: function optimization julia minimize minimization


【解决方案1】:

你应该给你的函数添加参数,这样你就可以确定你传递了正确的变量。那么你不应该使用fill(b,T),因为它会无用地分配一个新数组。此外,如果您遇到单变量问题,您应该只给求解器一个变量,并且按照文档 (Optim.jl/stable/#user/minimization/) 中的说明,您应该使用另一个求解器,例如 LBFGS()

总结如下:

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)

【讨论】:

  • 我做到了,谢谢。但是,错误消息保持不变:/
  • 我猜问题出在你填写b的方式上。 IE。像hcat(fill(b,T)...) 这样的东西也许可以工作?还是不好看
  • 问题不应该是 y 不应该是标量吗?因为b是一个数组,这是正确的
  • 不,正如你所说,y 是一个数组,但是如果你尝试[0.,0.] - [[0.,0.],[0.,0.]],它会给你同样的错误,因为它试图从第一个元素中减去第一个数组的第一个元素第二个数组。这就是问题所在。数组的形状不一样,第二个是嵌套数组,而第一个不是。
  • 好的,这是否来自优化的起点? ([0.0:0.0])?我试图改变它,但它不能只是 0.0?
【解决方案2】:

您可以通过以下方式复制您的错误:

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

这意味着您的y 不是预期的向量,而是标量。

解决此问题的一种可能方法是广播-

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

在 cmets 中已经提到的代码的另一个问题是全局变量。由于类型稳定性和性能,您永远不应该这样做。现在肯定是时候阅读了:https://docs.julialang.org/en/v1/manual/performance-tips/

【讨论】:

  • 谢谢,以后会注意全局变量。
  • 但是,在我的例子中,y 不是标量。当我打印它时,它是一个列向量。广播也不会改变结果
  • 你的objective不应该是一个标量而不是一个向量吗?
  • 如果您指的是目标函数的输出:那是一个标量,我刚刚检查过。但这不会产生这个错误,对吧?
猜你喜欢
  • 1970-01-01
  • 2015-12-18
  • 1970-01-01
  • 2022-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多