【问题标题】:Using automatic differentiation on a function that makes use of a preallocated array in Julia在使用 Julia 中预分配数组的函数上使用自动微分
【发布时间】:2018-09-03 21:08:21
【问题描述】:

我的长主题标题几乎涵盖了它。

我已经设法在下面的人为示例中隔离了我更大的问题。我无法弄清楚问题到底出在哪里,尽管我认为它与预分配数组的类型有关?

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】:

    如果您查看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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-17
      • 2021-02-03
      • 2017-06-25
      • 2020-05-03
      • 1970-01-01
      • 2018-05-15
      • 1970-01-01
      • 2020-05-27
      相关资源
      最近更新 更多