Optim.jl:负逆Hessian

mer*_*rch 9 optimization julia

我正在使用Optim.jl库来使用BFGS算法最小化Julia中的函数.今天,我问了一个关于同一个图书馆的问题,但为了避免混淆,我决定把它分成两部分.

我想在优化后得到负逆Hessian的估计值,以便进一步计算.

在Optim库的GitHub网站上,我找到了以下工作示例:

using Optim
rosenbrock(x) = (1.0 - x[1])^2 + 100.0 * (x[2] - x[1]^2)^2
result        = optimize(rosenbrock, zeros(2), BFGS())
Run Code Online (Sandbox Code Playgroud)

结果优化后,如何得到负逆Hessian ?它中是否有任何字段可以识别Hessian,Inverse Hessian或负Hessian?

编辑

感谢您的评论.你认为编辑"optimize.jl"会更有效率,这样函数也会返回逆Hessian吗?请参阅下面的工作示例 - 编辑已在第226行引入:

 if state.method_string == "BFGS"
         return MultivariateOptimizationResults(state.method_string,
                                                initial_x,
                                                f_increased ? state.x_previous : state.x,
                                                f_increased ? state.f_x_previous : state.f_x,
                                                iteration,
                                                iteration == options.iterations,
                                                x_converged,
                                                options.x_tol,
                                                f_converged,
                                                options.f_tol,
                                                g_converged,
                                                options.g_tol,
                                                f_increased,
                                                tr,
                                                state.f_calls,
                                                state.g_calls,
                                                state.h_calls), state.invH
    else
         return MultivariateOptimizationResults(state.method_string,
                                                 initial_x,
                                                 f_increased ? state.x_previous : state.x,
                                                 f_increased ? state.f_x_previous : state.f_x,
                                                 iteration,
                                                 iteration == options.iterations,
                                                 x_converged,
                                                 options.x_tol,
                                                 f_converged,
                                                 options.f_tol,
                                                 g_converged,
                                                 options.g_tol,
                                                 f_increased,
                                                 tr,
                                                 state.f_calls,
                                                 state.g_calls,
                                                 state.h_calls)
     end
Run Code Online (Sandbox Code Playgroud)

要不就:

return MultivariateOptimizationResults(state.method_string,
                                        initial_x,
                                        f_increased ? state.x_previous : state.x,
                                        f_increased ? state.f_x_previous : state.f_x,
                                        iteration,
                                        iteration == options.iterations,
                                        x_converged,
                                        options.x_tol,
                                        f_converged,
                                        options.f_tol,
                                        g_converged,
                                        options.g_tol,
                                        f_increased,
                                        tr,
                                        state.f_calls,
                                        state.g_calls,
                                        state.h_calls), state
Run Code Online (Sandbox Code Playgroud)

在优化后完全访问"状态".

编辑2

由于此更改将在新版本的Optim.jl库中引入,因此无需继续此讨论.现在,extended_traceafter_while!技巧工作.就个人而言,我更喜欢后者,所以我将结束讨论,给予@Dan Getz正确答案.

DSM*_*DSM 5

我知道一种方法,但是它是否值得,而不是自己估计逆Hessian,我不确定.如果通过Optim.Options(store_trace=true, extended_trace=true),则可以获得包含last_invH的优化路径的记录.例如,之后

result = optimize(rosenbrock, zeros(2), BFGS(),
                  Optim.Options(store_trace=true, extended_trace=true));
Run Code Online (Sandbox Code Playgroud)

我们可以得到

julia> result.trace[end]
    16     5.471433e-17     2.333740e-09
 * Current step size: 1.0091356566200325
 * g(x): [2.33374e-9,-1.22984e-9]
 * ~inv(H): [0.498092 0.996422; 0.996422 1.9983]
 * x: [1.0,1.0]


julia> result.trace[end].metadata["~inv(H)"]
2×2 Array{Float64,2}:
 0.498092  0.996422
 0.996422  1.9983  
Run Code Online (Sandbox Code Playgroud)

但是至少有两件事我不喜欢这种方法:

首先是开启extended_trace=true似乎是强制性的show_trace=true- 你会注意到我没有显示计算的输出!感觉像个臭虫.这可以通过设置show_every大的东西来缓解(虽然没有删除),或者通过完全重定向stdout来避免.

第二个是我们应该能够在不存储整个路径的情况下访问最后一个状态,但这是否实际上是一个问题取决于问题的大小.


Dan*_*etz 5

另一个不太理想的方法是连接内部Optim函数after_while!,该函数当前无效并使用它从最后一个状态中提取信息.

在Julia代码中,这看起来像:

julia> using Optim

julia> rosenbrock(x) = (1.0 - x[1])^2 + 100.0 * (x[2] - x[1]^2)^2
rosenbrock (generic function with 1 method)

julia> Optim.after_while!{T}(d, state::Optim.BFGSState{T}, method::BFGS, options)
  = global invH = state.invH

julia> result        = optimize(rosenbrock, zeros(2), BFGS())
Results of Optimization Algorithm
 * Algorithm: BFGS
 * Starting Point: [0.0,0.0]
 * Minimizer: [0.9999999926033423,0.9999999852005353]
 * Minimum: 5.471433e-17
 * Iterations: 16
 * Convergence: true
   * |x - x'| < 1.0e-32: false
   * |f(x) - f(x')| / |f(x)| < 1.0e-32: false
   * |g(x)| < 1.0e-08: true
   * f(x) > f(x'): false
   * Reached Maximum Number of Iterations: false
 * Objective Function Calls: 69
 * Gradient Calls: 69

julia> invH
2×2 Array{Float64,2}:
 0.498092  0.996422
 0.996422  1.9983  
Run Code Online (Sandbox Code Playgroud)

这对于使用全局变量并依赖于定义after_while!运行前/编译之前是不具吸引力的optimize(但可能在v0.6中已经解决了).

正如@DSM在他的回答中所指出的,希望访问最后一个优化器状态是很自然的.如果跟踪不是答案,也许这就是.