二重数を用いた自動微分

arg maxarg min\providecommandrecterf\providecommand\providecommand\providecommandPr

はじめに

先日、面白い記事を見つけた。二重数(下記ページでは「双対数」と呼ばれているが、Wikipediaでは「二重数」)を用いると、初等的な関数(ex,sinx,cosx,logx,)の加減乗除と合成関数で作られた関数の微分係数を機械的に計算するプログラムを比較的簡単に実装できるという話。

双対数を利用した自動微分についてのメモ

数学的な妥当性の説明が簡単に述べられているが、私の知識不足故か、素直に納得できないところがあったので、自分が気になった箇所について考えてみた。以下それについて述べる。

紹介されている数式の導出

f(a+bε)=f(a)+bεf(a)の導出

関数f:xGCf(x)Ca0Gを中心に冪級数展開可能であるとする。a,bCとし、aは収束領域に入っているものとする。

f(a+bε)=k=01k!f(k)(a0)(a+bεa0)k=f(a0)+k=11k!f(k)(a0)(a+bεa0)k=f(a0)+k=11k!f(k)(a0)l=0k(kl)(aa0)kl(bε)l=f(a0)+k=11k!f(k)(a0)[(aa0)k+bεk(aa0)k1]=k=01k!f(k)(a0)(aa0)k+bεk=11k!f(k)(a0)k(aa0)k1=f(a)+bε(ddxk=01k!f(k)(a0)(xa0)k)|x=a=f(a)+bεf(a)

f(a+εp)=f(a)+pf(a) の導出

f:xGRnf(x)Ca0を中心として冪級数展開可能であるとする。このときfは無限回微分可能であり、Youngの定理より/xi/xjが可換であることに注意する。a,pRとし、aは収束領域に入っているものとする。

f(a+εp)=f(a0+(aa0+εp))=f(a0)+k=11k![(aa0+εp)]k(f,a0)=f(a0)+k=11k![(aa0)+εp]k(f,a0)=f(a0)+k=11k!{[(aa0)]k+k[(aa0)]k1εp}(f,a0)=f(a0)+k=11k![(aa0)]k(f,a0)=+{(εp)k=11(k1)![(aa0)]k1}(f,a0)=f(a)+(εp)(k=01k![(aa0)]kf,a0)=f(a)+(εp)(g,a0)whereg:xf(x+(aa0))=f(a)+εp(f,a)

計算機での実装を意識

計算機で先述の冪級数展開を計算するわけにはいかない。実装上は、まず二重数クラスを定義し、f(a+bε)=f(a)+bεf(a)を初等的な関数(x,ex,sinx,cosx,tanx,logx,)について実装する。

双対数を利用した自動微分についてのメモの解説にあるように、f+fε,g+gε型の二重数同士の四則演算が好都合な結果をもたらすので、f(a+bε)=f(a)+bεf(a)を実装した関数同士の四則演算で構成されたユーザー定義関数hについては、引数にa+εを渡すだけで自動的にh(a)+h(a)が計算される。

Juliaでの実装

Juliaで実装したコードをGistで公開している: Automatic differentiation using Dual Number

投稿者: motchy

DSP and FPGA engineer working on measuring instrument.

コメントを残す