haskell - Numeric.AD - 类型变量脱离其作用域

标签 haskell automatic-differentiation

我正在尝试使用 automatic differentiation在 Haskell 中解决非线性控制问题,但在使其工作时遇到一些问题。我基本上有一个 cost 函数,它应该在给定初始状态的情况下进行优化。类型是:

data Reference a = Reference a deriving Functor
data Plant a = Plant a deriving Functor

optimize :: (RealFloat a) => Reference a -> Plant a -> [a] -> [[a]]
optimize ref plant initialInputs = gradientDescent (cost ref plant) initialInputs

cost :: (RealFloat a) => Reference a -> Plant a -> [a] -> a
cost = ...

这会导致以下错误消息:

Couldn't match expected type `Reference
                                (Numeric.AD.Internal.Reverse.Reverse s a)'
            with actual type `t'
  because type variable `s' would escape its scope
This (rigid, skolem) type variable is bound by
  a type expected by the context:
    Data.Reflection.Reifies s Numeric.AD.Internal.Reverse.Tape =>
    [Numeric.AD.Internal.Reverse.Reverse s a]
    -> Numeric.AD.Internal.Reverse.Reverse s a
  at test.hs:13:5-50
Relevant bindings include
  initialInputs :: [a] (bound at test.hs:12:20)
  ref :: t (bound at test.hs:12:10)
  optimize :: t -> t1 -> [a] -> [[a]] (bound at test.hs:12:1)
In the first argument of `cost', namely `ref'
In the first argument of `gradientDescent', namely
  `(cost ref plant)'

我什至不确定我是否正确理解错误。 refplant 的类型是否需要访问 s,这在 的第一个参数的范围内梯度下降?

有可能使这项工作吗?在寻找解决方案时,我尝试将问题简化为一个最小示例,发现以下定义会产生类似的错误消息:

optimize f inputs = gradientDescent f inputs 

这看起来很奇怪,因为 optimize = gradientDescent 没有产生任何错误。

最佳答案

cost ref plant 具有类型 [a] -> a 其中 aa 相同在签名中优化

optimize :: (RealFloat a) => Reference a -> Plant a -> [a] -> [[a]]
                                       ^          ^
                                       |          ------------
                                       ------------------v   v
optimize ref plant initialInputs = gradientDescent (cost ref plant) initialInputs
                                                         ^   ^
                                   -----------------------   |
                                   v          v---------------
cost :: (RealFloat a) => Reference a -> Plant a -> [a] -> a
cost = ...

但是gradientDescent的类型是

gradientDescent :: (Traversable f, Fractional a, Ord a) =>
                   (forall s. Reifies s Tape => f (Reverse s a) -> Reverse s a) -> 
                   f a -> [f a]

gradientDescent 的第一个参数需要能够接受(对于任何 )[Reverse s a] 并返回一个 Reverse s a,但是 cost ref plant 只能取 [a] 并返回一个 a

因为 ReferencePlant 都是 Functor,你可以转换 refplantReference a and Plant aReference (Reverse s a) and Plant (Reverse s a) by fmaping auto .

optimize :: (RealFloat a) => Reference a -> Plant a -> [a] -> [[a]]
optimize ref plant initialInputs = gradientDescent (cost (fmap auto ref) (fmap auto plant)) initialInputs

关于haskell - Numeric.AD - 类型变量脱离其作用域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32027302/

相关文章:

python - 为什么自动微分和梯度带需要使用上下文管理器?

Haskell:将偶数和奇数元素拆分为元组

haskell - 在 haskell 中一般遍历树的最简单方法

haskell - Haskell 中的幂级数

Haskell 递归方案 : Label the tree with intermediate results

performance - 难以理解 Haskell 内存分配行为

c++ - 使用 CoDiPack 自动区分

tensorflow - TensorFlow 中的 Wengert 列表在哪里?

python - 使用 Python JAX/Autograd 计算向量值函数的雅可比行列式

haskell - Haskell是否有任何反向模式自动微分的工作实现?