Scheme / Common Lisp / Clojure中的自动微分库

14

我听说 McCarthy 发明 Lisp 的一个最初的动力之一就是为了编写自动微分系统。尽管如此,我的谷歌搜索没有找到任何用于此目的的库/宏。是否存在任何Scheme/Common Lisp/Clojure库(宏)可接受函数 F 并返回计算 F 的导数 dF/dx 的函数?

我希望它支持具有多个参数的 F。用户将选择要针对其进行微分的 x。理想情况下,不同iator 将甚至适用于矢量值 F 和 x。

编辑: 有几个人提到了符号微分,符号微分和自动微分之间的差异是微妙的,但在Wikipedia中很好地概述了这一区别,特别在this picture中。在lisp中,这种区别不太明显,因为符号表达式可以直接转换为工作程序,但仍存在潜在的困难:

符号微分要求被微分的表达式由已知导数的操作组成。例如,有人提到了SICP中的一个宏的例子,该宏可以处理简单的sexps,如(+ y (* (x y))),并使用链式法则以及如何区分+*的知识来返回表示导数的sexp。我需要它能够处理像(* (foo x y) (bar x))这样的表达式,其中foobar可能会调用其他函数,这些函数的导数在区分时间不知道。
如果有一种方法可以获取像(foo x y)这样的表达式,并以卫生方式用xy替换任何参数的提及,并替换为其函数体,则这将是可以的。有吗?
此外,上述内容都没有涉及到当针对向量值参数微分向量值函数时出现的复杂情况...这正是大多数自动微分实现所针对的。

2
“numerical-methods”标签不适合您的问题,因为您所要求的是符号微分。通过数值微分找到函数f在x处的导数只需计算(f(x+dx)-f(x))/dx,其中dx是一个小值。 - Curd
3
添加 numerical-methods 标签,并不意味着我正在寻找执行数值微分的方法,因为很明显我不是。我只是想表明这个问题涉及与数值计算相关的函数(例如,评估实现数值方法的符号表达式)。 - SuperElectric
2
我理解你的感受。每当我提到自动微分时,人们总是将其与符号微分混淆,并且经常拒绝听取它们之间的区别。它绝对是一种“数值方法”,而且肯定不是“数值微分”。 - sigfpe
7个回答

8

Alexey Radul写道:

嗯,Scmutils中有自动微分系统

http://groups.csail.mit.edu/mac/users/gjs/6946/linux-install.htm

(这也恰好做符号微分)。我不知道其他已发布的实现,但您可以查看http://autodiff.org/

在Classical Mechanics的附录中还有一个实现它自己的不错的解释

http://mitpress.mit.edu/sicm/

以及学术文献。特别是前向模式并不难,尽管您必须小心避免扰动混乱。您可以参考Barak Pearlmutter和Jeffrey Mark Siskind的出版物,他们正在合作开发一种高性能的Lisp变体,该变体包含AD,并且一直在发表相关问题的文章。

http://scholar.google.com/scholar?q=Barak+Pearlmutter+and+Jeffrey+Mark+Siskind


谢谢!最后一个问题:您能否定义或提供“扰动混淆”这个术语的参考资料?我对这个术语不熟悉。 - SuperElectric
2
好的,我自己找到了答案,来自这篇论文:http://eprints.nuim.ie/archive/00000566/01/Perturbation.pdf "这些实现(...)在将微分算子应用于使用该算子的函数时,可能会计算出极不准确的结果。这个问题的根本原因是扰动混淆,即不能区分由不同微分算子调用引入的不同扰动。然后我们讨论如何避免扰动混淆。" - SuperElectric

4

3
如果你正在寻找一个符号系统,可以尝试 maxima(或这里)。它运行在许多Common-Lisp/OS平台组合上,但更像是一个完整的系统而不是一个库。
控制台输出可以,但与texmacs配合使用时可以产生非常漂亮的输出。
Maxima 5.23.2 http://maxima.sourceforge.net
using Lisp GNU Common Lisp (GCL) GCL 2.6.8 (a.k.a. GCL)
Distributed under the GNU Public License. See the file COPYING.
Dedicated to the memory of William Schelter.
The function bug_report() provides bug reporting information.
(%i1) diff(sin(1/x),x);
                                        1
                                     cos(-)
                                         x
(%o1)                              - ------
                                        2
                                       x

编辑

好的,看起来我误解了问题。通过一些谷歌搜索,建议在SCMUTILS 这里有一些工具,下载 这里, 用户手册 这里(从第24页开始查看)。


谢谢,但符号微分的外部工具不是我要找的。我已经编辑了问题以澄清这一点。 - SuperElectric
应该可以将Maxima作为任何通用Lisp程序的库使用(因此它可以从宏内部使用),因此它并不是那么“外部”。 - SK-logic
问题在于符号性。我正在寻找一个宏,它接受函数F并返回函数F'。我的意思是一个可求值的函数,它接受数字参数,而不是符号表达式。 - SuperElectric

2
有趣的是,scmutlis现已移植到Clojure。 还有很多工作要做,但是SICM书籍的前几章的代码似乎运行正常。
不同的差分例程和算子也似乎经过了我进行的少量测试,而且它甚至没有某些错误,这些错误似乎已经潜入了后来版本的scmutils中。
我认为scmutils涵盖了OP对于差异化的要求,因为它将正确处理已知和未知(文字)函数的导数。此页面提供了所需的详细信息以查看其符合要求的程度: SICM - Derivatives - Notation 在JVM上运行的一个优点是,如果需要,它将作为独立运行,甚至不需要安装Clojure!
它非常接近原始Scheme,对于Clojure语法做了最小的让步。
您可以在这里看到它: https://github.com/littleredcomputer/sicmutils#sicmutils ===
补充说明: 这是SicmUtils Clojure包中自动微分的示例。这是在各个互联网站点上流传的常见示例,要进行区分的代码如下:
    function f(x)
      y = x;
      for i=1...100
        y = sin(x+y);
      return y

在进行了一些Clojure处理之后,我们得到了:
   > (defn inner [y] (fn[x] (sin (+ x y))))
   > (defn f100 [x] (nth (iterate (inner x) x) 100))
   ;; value of derivative at 6
   > ((D f100) 6)
    => 0.51603111348625
   ;; value of the 4th derivative at 1
   > (((expt D 4) f100) 1)
    => -1.7853200839806143

1

这里是一个用Common Lisp实现的自动微分库。


1

-1

我已编辑问题,以明确说明这些示例并未提供我所寻找的一切。 - SuperElectric

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接