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

发布于 2024-10-15 16:58:29 字数 1026 浏览 3 评论 0原文

我听说 McCarthy 发明 Lisp 的最初动机之一是编写一个自动微分系统。尽管如此,我的谷歌搜索还没有产生任何用于执行此操作的库/宏。是否有任何计划/Common Lisp/Clojure 库(宏)用于获取函数 F 并返回计算 F 的导数的函数 dF/dx ?

我希望它支持具有多个参数的 F。用户可以选择其中哪个是要区分的 x。理想情况下,微分器甚至适用于向量值 F 和 x。

编辑:有几个人提到了符号微分。符号微分和自动微分之间的区别很微妙,但维基百科,特别是这张图片。这种区别在 lisp 中并不那么明显,其中符号表达式可以按原样转换为工作程序,但仍然存在潜在的困难:

符号微分要求被微分的表达式由具有已知导数的操作组成。例如,有人提到了 SICP 的宏示例,该宏通过 (+ y (* (xy))) 等简单的 sexps 进行搅动,并使用链式法则以及如何区分 的知识+*,返回表示导数的 sexp。我需要它来处理像 (* (foo xy) (bar x)) 这样的表达式,其中 foobar 可能会依次调用其他函数,其导数在微分时未知。

如果有一种方法可以采用 (foo xy) 之类的表达式并将其替换为其函数体,并用 x替换任何提到的参数,那就没问题了>y 以卫生的方式。有没有?

此外,上述方法都没有解决在区分向量值函数和向量值参数时出现的复杂性……这正是大多数自动微分实现所针对的。

I've heard that one of McCarthy's original motivations for inventing Lisp was to write a system for automatic differentiation. Despite this, my Google searches haven't yielded any libraries/macros for doing this. Are there any Scheme/Common Lisp/Clojure libraries (macros) out there for taking a function F and returning a function dF/dx that calculates the derivative of F?

I would want it to support F's with multiple arguments. The user would choose which of these is the x to differentiate with respect to. Ideally, the differentiator would work even for vector-valued F's and x's.

EDIT: Several people have mentioned symbolic differentiation. The difference between symbolic differentiation and automatic differentiation is a subtle one, but it's summarized well in Wikipedia, and particularly in this picture. This distinction isn't as strong in lisp, where symbolic expressions can be turned into working programs as-is, but there remains a potential difficulty:

Symbolic differentiation requires the expression being differentiated to be composed of operations with known derivatives. For example, someone mentioned SICP's example of a macro that churns through simple sexps like (+ y (* (x y))), and uses the chain rule, along with knowledge of how to differentiate + and *, to return a sexp that represents the derivative. I would need that to work with expressions like (* (foo x y) (bar x)), where foo and bar may in turn call other functions whose derivatives aren't known at differentiation time.

This would be fine if there's a way to take an expression like (foo x y) and replace it with its function body, substituting any mention of the arguments with x and y in a hygenic way. Is there?

Also, none of the above addresses complications that come about when differentiating vector-valued functions with respect to vector-valued arguments... which is what most autodifferentiation implementations are geared for.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

非要怀念 2024-10-22 16:58:30

Alexey Radul writes:

Well, there's the automatic differentiation system in Scmutils

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

(which coincidentally also does symbolic differentiation).
I don't know of any other released implementations, though you might
check http://autodiff.org/ .

There's also a nice explanation of how to implement it yourself in an
appendix of Structure and Interpretation of Classical Mechanics

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

as well as in the academic literature. Particularly forward mode is
not that hard, though you do have to be careful to avoid perturbation
confusion. You might consult the publications of Barak Pearlmutter
and Jeffrey Mark Siskind, who are collaborating on a high-performance
Lisp variant that incorporates AD and have been publishing on
surrounding issues.

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

素衣风尘叹 2024-10-22 16:58:30

还有另外两个包,都用于Scheme 中的自动微分。第二个是基于第一个,但被重新设计为鸡蛋。它们支持正向和反向模式。

There are two other packages, both for automatic differentiation in Scheme. The second is based on the first, but reworked as a chicken egg. These support both forward and reverse mode.

单调的奢华 2024-10-22 16:58:30

如果您正在寻找符号系统,您可以尝试 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 页起)。

If you are looking for a symbolic system, you could try maxima (or here). It runs on a number of Common-Lisp/OS platform combinations, but is more of a complete system than a library.

Console output is OK, but it can produce quite nice looking output when coupled with 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

EDIT

OK, looks like I misunderstood the question. A bit of googling suggests that there are some tools for this in SCMUTILS here, download here, user manual here (see p24 onwards).

一曲琵琶半遮面シ 2024-10-22 16:58:30

有趣的是,scmutlis 现在已移植到 Clojure。
还有很多工作要做,但 SICM 书的第一章中的代码似乎运行良好。

通过我所做的少量测试,微分例程和运算符似乎也还不错,甚至没有一些似乎已经渗透到更高版本的 scmutils 中的错误。

我认为 scmutils 涵盖了 OP 的重新微分要求,因为它将正确处理已知和未知(文字)函数的导数。此页面提供了查看其符合要求的程度所需的详细信息:
SICM - 衍生品 - 表示法

在 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

经过 Clojurifying 后我们有

   > (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

It may be of interest that scmutlis has now been ported to Clojure.
There is a lot more work to be done, but the code in the fist chapters of the SICM book seems to be running fine.

Differentiation routines and operators also seem OK with what little testing I've done, and it is even free of some bugs that appear to have crept into later versions of scmutils.

I think that scmutils covers OP's requirements re differentiation, since it will correctly handle derivatives of both known and unknown (literal) functions. This page gives the details needed to see how well it fits requirements:
SICM - Derivatives - Notation

One of the advantages of running on the JVM, is that will run as a standalone if so required, no need even to install Clojure!

It is very close to the original Scheme, minimal concessions made for Clojure syntax.

You can see it here:
https://github.com/littleredcomputer/sicmutils#sicmutils

===

Addendum:
Here is an example of automatic differentiation in the SicmUtils Clojure package. This is a common example circulating on various Internet sites, the code to be differentiated is

    function f(x)
      y = x;
      for i=1...100
        y = sin(x+y);
      return y

After Clojurifying it a bit we have

   > (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
顾忌 2024-10-22 16:58:30

这里是 AD 在 common lisp 中的实现。

Here is an implementation of AD in common lisp.

删除→记忆 2024-10-22 16:58:30

值得一试 Deriva,它为 Clojure 和 Java 提供自动微分:

您可能还对expresso感兴趣,它更多的是关于数值表达式操作,但仍然具有一些差异化功能,并且可能适合大多数AD用例:

Worth checking out Deriva, which does Automatic Differentiation for both Clojure and Java:

You may also be interested in expresso, which is more about numerical expression manipulation but still has some differentiation features and could probably be adapted to most AD use cases:

泪冰清 2024-10-22 16:58:30

谷歌搜索“lisp 符号微分”
你会发现很多例子,例如

http://mitpress.mit .edu/sicp/full-text/sicp/book/node39.html

Google for 'lisp symbolic differentiation'
and you will find plenty examples, e.g.

http://mitpress.mit.edu/sicp/full-text/sicp/book/node39.html

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文