如何在 Julia 中独立于 Optim.jl 使用 Linesearches.jl 模块?

Sim*_*ner 5 optimization numerical-methods julia

我有 L-BFGS 的实现,并且想从 LineSearches.jl 调用行搜索进行比较。然而,文档非常稀疏,并且仅关注在 Optim.jl 上下文中使用 Linesearches.jl。我找不到任何如何独立使用 Linesearches.jl 的示例。

Asb*_*eth 0

我在文档中创建了一个示例,说明如何将LineSearches算法与定制优化器一起使用。latest

\n\n

请注意,该示例当前需要 LineSearches master,但应该很快就会可用v6.0.0

\n\n

这是完整的示例,以防链接中断:(编辑:使用简化过程的新示例代码进行更新。)

\n\n

在没有 Optim/NLsolve 的情况下使用 LineSearches

\n\n

假设我们已经编写了梯度下降优化算法,但想要\n尝试不同的线搜索算法。\n该算法的实现如下。

\n\n
function gdoptimize(f, g!, fg!, x0::AbstractArray{T}, linesearch,\n                    maxiter::Int = 10000,\n                    g_rtol::T = sqrt(eps(T)), g_atol::T = eps(T)) where T <: Number\n    x = copy(x0)\n    gvec = similar(x)\n    g!(gvec, x)\n    fx = f(x)\n\n    gnorm = norm(gvec)\n    gtol = max(g_rtol*gnorm, g_atol)\n\n    # Univariate line search functions\n    \xcf\x95(\xce\xb1) = f(x .+ \xce\xb1.*s)\n    function d\xcf\x95(\xce\xb1)\n        g!(gvec, x .+ \xce\xb1.*s)\n        return vecdot(gvec, s)\n    end\n    function \xcf\x95d\xcf\x95(\xce\xb1)\n        phi = fg!(gvec, x .+ \xce\xb1.*s)\n        dphi = vecdot(gvec, s)\n        return (phi, dphi)\n    end\n\n    s = similar(gvec) # Step direction\n\n    iter = 0\n    while iter < maxiter && gnorm > gtol\n        iter += 1\n        s .= -gvec\n\n        d\xcf\x95_0 = dot(s, gvec)\n        \xce\xb1, fx = linesearch(\xcf\x95, d\xcf\x95, \xcf\x95d\xcf\x95, 1.0, fx, d\xcf\x95_0)\n\n        @. x = x + \xce\xb1*s\n        g!(gvec, x)\n        gnorm = norm(gvec)\n    end\n\n    return (fx, x, iter)\nend\n
Run Code Online (Sandbox Code Playgroud)\n\n

请注意,出于计算效率的原因,有许多优化和线搜索算法允许用户同时评估目标和梯度。\n我们已将此功能作为输入函数包含在算法中,\nfg!并且即使梯度下降算法没有明确使用它,许多 LineSearches 算法也会这样做。

\n\n

梯度下降gdoptimize方法选择下降方向并调用线搜索算法, linesearch该算法返回步长\xce\xb1和目标值fx = f(x + \xce\xb1*s)

\n\n

函数 \xcf\x95 和 d\xcf\x95 表示单变量目标\n及其导数,由线搜索算法使用。\n要在fg!优化器中使用函数调用,某些线搜索\n需要函数\ xcf\x95d\xcf\x95 同时返回单变量目标和\n导数。

\n\n

优化罗森布洛克

\n\n

这是一个例子来展示我们如何组合gdoptimizeLineSearches\n来最小化 Rosenbrock 函数,该函数的定义为

\n\n
f(x) = (1.0 - x[1])^2 + 100.0 * (x[2] - x[1]^2)^2\n\nfunction g!(gvec, x)\n    gvec[1] = -2.0 * (1.0 - x[1]) - 400.0 * (x[2] - x[1]^2) * x[1]\n    gvec[2] = 200.0 * (x[2] - x[1]^2)\n    gvec\nend\n\nfunction fg!(gvec, x)\n    g!(gvec, x)\n    f(x)\nend\n
Run Code Online (Sandbox Code Playgroud)\n\n

我们现在可以使用gdoptimizewithBackTracking从给定的初始条件\n优化 Rosenbrock 函数x0

\n\n
x0 = [-1., 1.0]\n\nusing LineSearches\nls = BackTracking(order=3)\nfx_bt3, x_bt3, iter_bt3 = gdoptimize(f, g!, fg!, x0, ls)\n
Run Code Online (Sandbox Code Playgroud)\n\n

有趣的是,StrongWolfe线搜索在一次迭代中收敛,而\n所有其他算法需要数千次迭代。\n由于初始条件的特定选择,这只是运气

\n\n
ls = StrongWolfe()\nfx_sw, x_sw, iter_sw = gdoptimize(f, g!, fg!, x0, ls)\n
Run Code Online (Sandbox Code Playgroud)\n