#自动微分 #前向 #微分 #自动 # #AD

fwd_ad

前向自动微分,允许用户管理内存位置并最小化复制

2个不稳定版本

0.2.0 2020年5月18日
0.1.0 2020年4月29日

#486 in 数学

MIT许可协议

46KB
1K SLoC

Fwd:AD是一个前向自动微分的crate

此crate允许您轻松编写对双数的操作,并执行前向自动微分。它使用户能够用最小的分配编写自动微分代码。

主要卖点

  1. 默认无克隆。Fwd:AD在其函数中永远不会克隆内存(除了to_owning()std::ops实现之外)并利用Rust的所有权系统确保内存正确性,并将何时进行克隆的决定权留给用户。
  2. 按需自动克隆。如果传递了implicit-clone功能,Fwd:AD将在需要时隐式克隆Dual。是否克隆完全由类型系统决定,因此是在编译时完成的。
  3. 内存位置泛型:Fwd:AD的结构对容器类型进行泛型化,允许它们支持您选择的任何容器:使用堆的Vec,如果你更喜欢栈,则使用数组,或其它。例如,它可以与&mut [f64]一起使用,以允许一个不需要在边界处复制内存的FFI API。

示例

详细示例可在examples/目录中找到,但以下是一些片段。

Rosenbrock函数最小化

extern crate fwd_ad;
use fwd_ad::*;

// The factor by which we will descend along the gradient.
// Rosenbrock function is pretty steep so its quite small.
const ALPHA : f64 = 1e-3;

fn main() {
    // Create two duals with two derivatives each, as well as
    // closures getdx and getdy to get their corresponding derivative
    generate_duals!{
        x = 0.; @ getdx
        y = 0.; @ getdy
    }
    for _ in 0..10000 {
        let xval : f64 = x.val();
        let yval : f64 = y.val();

        let res = (x.clone() - 1.).powf(2.) + 100.*(y-x.powf(2.)).powf(2.);
        println!("At x={}, y={}, the rosenbrock function is {}",xval, yval, res.val());

        generate_duals!{
            newx = xval - ALPHA*getdx(res.view());
            newy = yval - ALPHA*getdy(res.view());
        }
        x = newx;
        y = newy;
    }
}

简短教程

Fwd:AD的主要类型是Dual<Container, OM, F>结构。此结构由三种类型参数化,分别是

  1. Container 类型指示用于存储结构内容的“容器”。典型示例包括 Vec<F>[F; n]&mut [F]&[F]
  2. OM 是“拥有模式”,有两种可能性之一:表示“读写”的 RW,表示 Dual 的内容可写,因此可以在计算期间重复使用,以及表示只读的 RO
  3. F 是标量类型,通常是 f32f64,但你可以选择使用不同的类型。

Dual 包装其容器,该容器必须是“可读为 [F] 的切片”。该标量切片的第一个元素是 dual 的实际值,接下来的是关于连续变量的导数。

为了减轻编写长类型名称的负担,在 instanciations 模块中定义了规范的对拥有/查看 dual。

Fwd:AD Traits

Fwd:AD 依赖于几个特质以足够通用。用户可能需要实现的特质位于 traits 模块中。

  • ROAble(或 RWAble)是应该由能够读取(或写入)其内容的容器实现的特质。所有容器类型都必须实现 ROAble。这些特质类似于 AsRef/AsMut 来自 core,并提供了一个泛型实现。
  • ToViewToOwning 是用于定义规范“拥有”(可以是 RW)和“查看”(只有 RO 容量)容器对应关系的特质。
  • Scalar 是代表标量数字的特质,它是 num_traits 的各种特质的超特质,因此这是你应该寻求实现的内容。

注意事项:由于你不能在外部类型上实现外部特质,你可能会发现自己在使用不常见的容器或标量类型时受到限制。如果是这样,请与该crate的维护者联系。

与其他(正向)AD Rust 库的比较

最后更新列表示检查相应crate的最后时间。自那时以来,crate可能已发生变化。

crate 版本 多元 高阶 最后更新
Fwd:AD 0.1.0 ✔️ 2020-04-29
ad 0.1.0 2020-01-01
autodiff 0.1.9 2019-11-07
descent¹ 0.3 ✔️ (2nd order?) 2018-12-10
dual 0.2.0 2015-12-25
dual_num 0.2.7 2019-04-03
hyperdual² 0.3.4 ✔️ 2020-02-08
peroxide 0.21.7 (2nd order) 2020-04-21
  1. descent 自动微分似乎很有前途,但文档不多,并且与 IP-OPT 接口混合。
  2. hyperdual 与 Fwd:AD 有类似特性,但所有操作都会在 Fwd:AD 尝试重用现有内存时进行分配。

依赖关系

~0.1–11MB
~96K SLoC