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

时间:2018-05-12 22:38:44

标签: optimization julia numerical-methods

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

1 个答案:

答案 0 :(得分:0)

我创建了一个示例,说明如何在custom-made optimizer中使用LineSearches算法和latest documentation

请注意,该示例目前需要LineSearches master,但很快就会在v6.0.0中提供。

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

使用没有Optim / NLsolve的LineSearches

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

function gdoptimize(f, g!, fg!, x0::AbstractArray{T}, linesearch,
                    maxiter::Int = 10000,
                    g_rtol::T = sqrt(eps(T)), g_atol::T = eps(T)) where T <: Number
    x = copy(x0)
    gvec = similar(x)
    g!(gvec, x)
    fx = f(x)

    gnorm = norm(gvec)
    gtol = max(g_rtol*gnorm, g_atol)

    # Univariate line search functions
    ϕ(α) = f(x .+ α.*s)
    function dϕ(α)
        g!(gvec, x .+ α.*s)
        return vecdot(gvec, s)
    end
    function ϕdϕ(α)
        phi = fg!(gvec, x .+ α.*s)
        dphi = vecdot(gvec, s)
        return (phi, dphi)
    end

    s = similar(gvec) # Step direction

    iter = 0
    while iter < maxiter && gnorm > gtol
        iter += 1
        s .= -gvec

        dϕ_0 = dot(s, gvec)
        α, fx = linesearch(ϕ, dϕ, ϕdϕ, 1.0, fx, dϕ_0)

        @. x = x + α*s
        g!(gvec, x)
        gnorm = norm(gvec)
    end

    return (fx, x, iter)
end

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

Gradient Descent gdoptimize方法选择下降方向并调用 行搜索算法linesearch返回步长α和 客观价值fx = f(x + α*s)

函数φ和dφ表示单变量目标 及其衍生物,由线搜索算法使用。 要在优化器中使用fg!函数调用,请进行一些行搜索 需要一个函数φdφ,它返回单变量目标和 同时衍生出来。

优化Rosenbrock

以下是一个示例,说明我们如何合并gdoptimizeLineSearches 最小化Rosenbrock函数,该函数由

定义
f(x) = (1.0 - x[1])^2 + 100.0 * (x[2] - x[1]^2)^2

function g!(gvec, x)
    gvec[1] = -2.0 * (1.0 - x[1]) - 400.0 * (x[2] - x[1]^2) * x[1]
    gvec[2] = 200.0 * (x[2] - x[1]^2)
    gvec
end

function fg!(gvec, x)
    g!(gvec, x)
    f(x)
end

我们现在可以使用gdoptimizeBackTracking来优化Rosenbrock功能 来自给定的初始条件x0

x0 = [-1., 1.0]

using LineSearches
ls = BackTracking(order=3)
fx_bt3, x_bt3, iter_bt3 = gdoptimize(f, g!, fg!, x0, ls)

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

ls = StrongWolfe()
fx_sw, x_sw, iter_sw = gdoptimize(f, g!, fg!, x0, ls)