在Julia中使用预分配数组的函数自动区分

问题描述 投票:3回答:1

我的长篇题目几乎涵盖了它。

我已设法在下面的下面的设计示例中找出我更大的问题。我无法弄清楚问题的确切位置,但我想它与预分配数组的类型有关?

using ForwardDiff

function test()

    A = zeros(1_000_000)

    function objective(A, value)
        for i=1:1_000_000
            A[i] = value[1]
        end

        return sum(A)
    end

    helper_objective = v -> objective(A, v)

    ForwardDiff.gradient(helper_objective, [1.0])

end

错误如下:

ERROR: MethodError: no method matching Float64(::ForwardDiff.Dual{ForwardDiff.Tag{getfield(Main, Symbol("##69#71")){Array{Float64,1},getfield(Main, Symbol("#objective#70")){Array{Float64,1}}},Float64},Float64,1})

在我自己的问题(这里没有描述)我有一个功能,我需要使用Optim进行优化,以及它提供的自动区分,这个函数使用我想要预分配的大矩阵,以加快我的代码。非常感谢。

arrays optimization julia automatic-differentiation
1个回答
2
投票

如果你看看http://www.juliadiff.org/ForwardDiff.jl/latest/user/limitations.html,你会发现:

目标函数必须通常写入足以接受T <:Real类型的数字作为输入(或这些数字的数组)(...)这也意味着在函数中使用的任何分配的存储也必须是通用的。

以这里为例https://github.com/JuliaDiff/ForwardDiff.jl/issues/136#issuecomment-237941790

这意味着您可以执行以下操作:

function test()
    function objective(value)
        for i=1:1_000_000
            A[i] = value[1]
        end
        return sum(A)
    end
    A = zeros(ForwardDiff.Dual{ForwardDiff.Tag{typeof(objective), Float64},Float64,1}, 1_000_000)
    ForwardDiff.gradient(objective, [1.0])
end

但是我不认为这会为你节省很多分配,因为它类型不稳定。

你可以做的是将objectiveA包装在这样的模块中:

using ForwardDiff

module Obj

using ForwardDiff

function objective(value)
    for i=1:1_000_000
        A[i] = value[1]
    end
    return sum(A)
end
const A = zeros(ForwardDiff.Dual{ForwardDiff.Tag{typeof(objective), Float64},Float64,1}, 1_000_000)

end

现在这个:

ForwardDiff.gradient(Obj.objective, [1.0])

应该快。

编辑

这也有效(虽然它是类型不稳定但在一个问题较少的地方):

function test()::Vector{Float64}
    function objective(A, value)
        for i=1:1_000_000
            A[i] = value[1]
        end

        return sum(A)
    end
    helper_objective = v -> objective(A, v)
    A = Vector{ForwardDiff.Dual{ForwardDiff.Tag{typeof(helper_objective), Float64},Float64,1}}(undef, 1_000_000)
    ForwardDiff.gradient(helper_objective, [1.0])
end
© www.soinside.com 2019 - 2024. All rights reserved.