Julia 自动微分——它完全失效了吗?

标签 julia

Julia 的 ForwardDiff 可以处理闭包吗?如果不是,它就不是那么有用,但如果是,我下面哪里出错了?

using ForwardDiff
function make_add(x)
   foo = y::Vector -> y+x
   return foo
end

zulu = make_add(17)

g = x-> ForwardDiff.gradient(zulu, x)

g([1, 2, 3])

MethodError: no method matching extract_gradient! 
  (::Type{ForwardDiff.Tag{##1#2{Int64},Int64}},  

 `::Array{Array{ForwardDiff.Dual{ForwardDiff.Tag{##1#2{Int64},Int64},Int64,3},1},1}, ::Array{ForwardDiff.Dual{ForwardDiff.Tag{##1#2{Int64},Int64},Int64,3},1})
Closest candidates are:
  extract_gradient!(::Type{T}, ::AbstractArray, ::ForwardDiff.Dual) where T at /home/jrun/.julia/v0.6/ForwardDiff/src/gradient.jl:76
  extract_gradient!(::Type{T}, ::AbstractArray, ::Real) where T at /home/jrun/.julia/v0.6/ForwardDiff/src/gradient.jl:75
  extract_gradient!(::Type{T}, ::DiffResults.DiffResult, ::ForwardDiff.Dual) where T at /home/jrun/.julia/v0.6/ForwardDiff/src/gradient.jl:70
  ...

Stacktrace:
 [1] gradient(::Function, ::Array{Int64,1}, ::ForwardDiff.GradientConfig{ForwardDiff.Tag{##1#2{Int64},Int64},Int64,3,Array{ForwardDiff.Dual{ForwardDiff.Tag{##1#2{Int64},Int64},Int64,3},1}}, ::Val{true}) at /home/jrun/.julia/v0.6/ForwardDiff/src/gradient.jl:17
 [2] gradient(::Function, ::Array{Int64,1}, ::ForwardDiff.GradientConfig{ForwardDiff.Tag{##1#2{Int64},Int64},Int64,3,Array{ForwardDiff.Dual{ForwardDiff.Tag{##1#2{Int64},Int64},Int64,3},1}}) at /home/jrun/.julia/v0.6/ForwardDiff/src/gradient.jl:15
 [3] (::##3#4)(::Array{Int64,1}) at ./In[8]:1`

编辑事实上这与闭包无关。简单地说:

h = x-> ForwardDiff.gradient(x-> x+17.0, x)

以完全相同的方式炸弹

最佳答案

ForwardDiff.gadient 的文档指出:

This method assumes that isa(f(x), Real).

问题是你的函数返回一个向量而不是标量,因此你需要使用jacobian(它接受数组作为返回值):

julia> function make_add(x)
          foo = y::Vector -> y .+ x
             return foo
             end
make_add (generic function with 1 method)

julia> zulu = make_add(17)
#27 (generic function with 1 method)

julia> g = x-> ForwardDiff.jacobian(zulu, x)
#29 (generic function with 1 method)

julia> g([1, 2, 3])
3×3 Array{Int64,2}:
 1  0  0
 0  1  0
 0  0  1

另请注意,我在 + 之前添加了一个点(因此它显示为 y .+ x),因为在当前版本的 Julia 1.0 中,不允许您添加标量到向量,无需广播。

关于Julia 自动微分——它完全失效了吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51804016/

相关文章:

julia - 在 Julia 中访问结构数组中字段的最佳方法

julia - 有效地 reshape 数组 2D -> 3D

Julia Studio 中的 Julia 版本

julia - Julia中的聚类和距离计算

Julia 默认数字类型

fortran - 使用 Julia 编译 Fortran77

julia - 在 Julia 中计算复厄米稀疏矩阵的特征值

loops - 在 for 循环中,何时评估循环参数?

multithreading - 如何杀死 Julia 中的任务?

Julia:成对距离的嵌套循环真的很慢