数学とコンピュータ代数において、自動微分(自動微分、オートディフ、またはAD)は、アルゴリズム微分、計算微分とも呼ばれ、[1] [2]は、コンピュータプログラムによって指定された関数の偏微分を評価するための一連の手法です。
自動微分法は、どんなに複雑なコンピュータ計算でも、一連の基本的な算術演算 (加算、減算、乗算、除算など) と基本的な関数 ( exp、log、sin、cosなど) を実行するという事実を利用します。これらの演算に連鎖律を繰り返し適用することで、任意の順序の偏導関数を、作業精度まで正確に、元のプログラムよりも最大で小さな定数倍の算術演算を使用して自動的に計算できます。
他の差別化方法との違い

自動微分は、記号微分や数値微分とは異なります。記号微分では、コンピュータ プログラムを単一の数式に変換することが難しく、コードが非効率的になる可能性があります。数値微分 (有限差分法)では、離散化プロセスとキャンセルで丸め誤差が発生する可能性があります。これらの古典的な方法は両方とも、複雑性と誤差が増加する高次の導関数の計算に問題があります。最後に、これらの古典的な方法は両方とも、勾配ベースの最適化アルゴリズムに必要な、多くの入力に関する関数の偏導関数の計算が遅いです。自動微分は、これらの問題をすべて解決します。
アプリケーション
自動微分は機械学習の分野で特に重要です。たとえば、手動で計算された導関数を使用せずに、ニューラル ネットワークで バックプロパゲーションを実装できます。
順方向蓄積と逆方向蓄積
合成関数の偏微分の連鎖律
自動微分化の基本は、合成関数の偏微分の連鎖律によって提供される微分分解である。単純な合成の場合、 連鎖律は次式を与える。
自動微分化の2つのタイプ
通常、自動微分化には 2 つの異なるモードが提示されます。
- 前方累積(ボトムアップ、前方モード、接線モードとも呼ばれる)
- 逆蓄積(トップダウン、逆モード、または随伴モードとも呼ばれる)
順方向累積は、連鎖律を内側から外側へ(つまり、最初に を計算し、次に 、最後に)走査することを指定します。一方、逆方向累積は、外側から内側へ(最初に を計算し、次に、最後に)走査することを指定します。より簡潔に言うと、
- 前方累積は、再帰関係を計算します。 、および、
- 逆累積は、の再帰関係を計算します。
偏導関数の値はシードと呼ばれ、前方または後方に伝播され、最初はまたはです。前方累積は関数を評価し、1 つのパスで 1 つの独立変数に関する導関数を計算します。したがって、各独立変数について、その独立変数に関する導関数が 1 ( ) に設定され、その他すべての導関数が 0 ( ) に設定される個別のパスが必要です。対照的に、逆累積では、偏導関数に対して評価された部分関数が必要です。したがって、逆累積は最初に関数を評価し、追加のパスですべての独立変数に関する導関数を計算します。
これら 2 つのタイプのどちらを使用するかは、スイープの数によって異なります。1回のスイープの計算の複雑さは、元のコードの複雑さに比例します。
- 関数f : R n → R m ( n ≪ m)の場合、逆方向の累算よりも順方向の累算の方が効率的です。逆方向の累算ではm回のスイープが必要ですが、n 回のスイープだけで済むためです。
- 逆累積は、関数f : R n → R m ( n ≫ m)の場合、順累積よりも効率的です。順累積の場合はn 回のスイープが必要ですが、逆累積の場合はm 回のスイープしか必要ないためです。
機械学習で使用される技術である多層パーセプトロンにおける誤差の逆伝播は、逆累積の特殊なケースである。[2]
順方向蓄積は1964年にRE Wengertによって導入されました。[3] Andreas Griewankによると、逆方向蓄積は1960年代後半から提案されていましたが、発明者は不明です。[4] Seppo Linnainmaaは1976年に逆方向蓄積を発表しました。 [5]
前方蓄積

順方向累積 AD では、まず、微分化を実行する独立変数を固定し、各部分式の導関数を再帰的に計算します。紙とペンによる計算では、連鎖律に 内部関数の導関数を繰り返し代入する必要があります。これは、ヤコビアン の行列積として複数の変数に一般化できます。
逆累積と比較すると、順累積は導関数情報の流れが評価の順序と一致するため、自然で実装が簡単です。各変数には、ドットで示されるように、導関数(記号式ではなく数値として保存) が追加されます 。次に、導関数は評価手順と同期して計算され、連鎖律によって他の導関数と結合されます。
連鎖律を使用すると、計算グラフに先行要素がある場合、次のようになります。

例として、次の関数を考えてみましょう。 わかりやすくするために、個々の部分式には変数 というラベルが付けられています。
微分を行う独立変数の選択は、シード値ẇ 1とẇ 2に影響します。この関数のx 1に関する導関数に関心がある場合、シード値は次のように設定する必要があります。
シード値を設定すると、図に示すように、値は連鎖律に従って伝播します。図 2 は、このプロセスを計算グラフとして図示したものです。
この例の関数の勾配を計算するには、 だけでなく も必要であり、シード値 を使用して計算グラフ上で追加のスイープが実行されます。
実装
擬似コード
前方累積は、関数と導関数(ただし、それぞれ独立変数 1 つずつ)を 1 回のパスで計算します。関連するメソッド呼び出しでは、式Z が変数Vに関して導出されることが想定されています。メソッドは、評価された関数とその導関数のペアを返します。メソッドは、変数に到達するまで式ツリーを再帰的にトラバースします。この変数に関する導関数が要求された場合、その導関数は 1 で、そうでない場合は 0 です。次に、部分関数と部分導関数が評価されます。[6]
タプル< float 、float > assessAndDerive (式Z 、変数V ) { if isVariable ( Z ) if ( Z = V ) return { valueOf ( Z ), 1 }; else return { valueOf ( Z ), 0 }; else if ( Z = A + B ) { a 、a ' } = assessAndDerive ( A 、V ); { b 、b ' } = assessAndDerive ( B 、V ); return { a + b 、a ' + b ' }; else if ( Z = A - B ) { a 、a ' } = assessAndDerive ( A 、V ); { b 、b ' } = assessAndDerive ( B 、V ); return { a - b 、a ' - b ' }; else if ( Z = A * B ) { a 、a ' } = assessAndDerive ( A 、V ); { b 、b ' } = assessAndDerive ( B 、V );戻り値{ a * b 、b * a ' + a * b ' }; }
C++
#include <iostream> struct ValueAndPartial { float value , partial ; }; struct Variable ; struct Expression { virtual ValueAndPartial assessAndDerive ( Variable * variable ) = 0 ; }; struct Variable : public Expression { float value ; Variable ( float value ) : value ( value ) {} ValueAndPartial assessAndDerive ( Variable * variable ) { float partial = ( this == variable ) ? 1.0f : 0.0f ; return { value , partial }; } }; struct Plus : public Expression { Expression * a , * b ; Plus ( Expression * a , Expression * b ) : a ( a ), b ( b ) {} ValueAndPartial assessAndDerive ( Variable * variable ) { auto [ valueA , partialA ] = a -> assessAndDerive ( variable ); auto [ valueB , partialB ] = b -> evaluateAndDerive (変数); return { valueA + valueB , partialA + partialB }; } }; struct Multiply : public Expression { Expression * a , * b ; Multiply ( Expression * a ,
Expression * b ) : a ( a ), b ( b ) {} ValueAndPartial assessAndDerive ( Variable * variable ) { auto [ valueA , partialA ] = a -> assessAndDerive ( variable ); auto [ valueB , partialB ] = b -> assessAndDerive ( variable ); return { valueA * valueB , valueB * partialA + valueA * partialB }; } }; int main () { // 例: (x, y) = (2, 3) における z = x * (x + y) + y * y の部分値を求めるVariable x ( 2 ), y ( 3 ); Plus p1 ( & x , & y ); Multiply m1 ( & x , & p1 ); Multiply m2 ( & y , & y ); Plus z ( & m1 , & m2 ); float xPartial = z .evaluateAndDerive ( & x ) . partial ; float yPartial = z .evaluateAndDerive ( & y ) . partial ; std :: cout << "∂z/∂x = " << xPartial << ", " << "∂z/∂y = " << yPartial << std :: endl ; // 出力: ∂z/∂x = 7, ∂z/∂y = 8 return 0 ; }
逆蓄積

逆累積 AD では、微分する従属変数が固定され、各部分式に関して導関数が再帰的に計算されます。紙とペンによる計算では、外部関数の導関数が連鎖律に繰り返し代入されます。
逆累積では、関心のある量はバーで示される随伴量であり、これは選択された従属変数の部分式に関する導関数です。
連鎖律を使用すると、計算グラフに後続がある場合:
逆累積は、連鎖律を外側から内側へ、または図 3 の計算グラフの場合は上から下へ横断します。例の関数はスカラー値であるため、導関数計算のシードは 1 つだけであり、計算グラフのスイープは 1 回のみで (2 成分) 勾配を計算できます。これは、順方向累積と比較すると作業量が半分になりますが、逆累積では、中間変数 w i と、それらを生成した命令を「テープ」または Wengert リスト[7]と呼ばれるデータ構造に格納する必要があります(ただし、Wengert は逆累積ではなく、順方向累積を公開しました[3] )。計算グラフが大きい場合は、メモリを大量に消費する可能性があります。中間変数のサブセットのみを保存し、評価を繰り返すことで必要な作業変数を再構築することで、この問題をある程度軽減できます。この手法は再マテリアライゼーションと呼ばれます。チェックポイントは、中間状態を保存するためにも使用されます。

逆累積を使用して導関数を計算するための操作を次の表に示します (逆の順序に注意してください)。
- 微分を計算する演算
計算のデータフローグラフを操作して、元の計算の勾配を計算できます。これは、各主ノードに随伴ノードを追加することで行われます。随伴ノードは、主エッジと平行ですが、反対方向に流れる随伴エッジで接続されます。随伴グラフのノードは、主ノードで計算された関数の導関数による乗算を表します。たとえば、主ノードで加算を行うと随伴ノードでファンアウトが発生します。主ノードでファンアウトが発生すると随伴ノードで加算が発生します。[a]主ノードで単項関数y = f ( x )を実行すると、随伴ノードでx̄ = ȳ f ′( x )が発生します。など。
実装
疑似コード
逆累積には 2 つのパスが必要です。順方向パスでは、関数が最初に評価され、部分的な結果がキャッシュされます。逆方向パスでは、偏導関数が計算され、以前に導出された値が逆伝播されます。対応するメソッド呼び出しでは、式Zが導出され、親式の導出値でシードされることが想定されています。最上位の式、Z に関して導出された Z の場合、これは 1 です。メソッドは、変数に到達するまで式ツリーを再帰的にトラバースし、現在のシード値を導出式に追加します。[8] [9]
void derive ( Expression Z 、float seed ) { if isVariable ( Z ) partialDerivativeOf ( Z ) += seed ; else if ( Z = A + B ) derive ( A 、seed ); derive ( B 、seed ); else if ( Z = A - B ) derive ( A 、seed ); derive ( B 、- seed ); else if ( Z = A * B ) derive ( A 、valueOf ( B ) * seed ); derive ( B 、valueOf ( A ) * seed ); }
C++
#include <iostream> struct Expression { float value ; virtual void assess () = 0 ; virtual void derive ( float seed ) = 0 ; }; struct Variable : public Expression { float partial ; Variable ( float value ) { this -> value = value ; partial = 0.0f ; } void assess () {} void derive ( float seed ) { partial += seed ; } }; struct Plus : public Expression { Expression * a , * b ; Plus ( Expression * a , Expression * b ) : a ( a ), b ( b ) {} void assess () { a -> assess (); b -> assess (); value = a -> value + b -> value ; } void derive ( float seed ) { a -> derive ( seed ); b -> derive ( seed ); } }; struct Multiply : public Expression { Expression * a , * b ;乗算(式* a 、式* b ) : a ( a )、b ( b ) {} void評価() { a ->
評価();
b ->評価(); value = a -> value * b -> value ; } void derive ( float seed ) { a -> derive ( b -> value * seed ); b -> derive ( a -> value * seed ); } }; int main () { // 例: (x, y) = (2, 3) における z = x * (x + y) + y * y の部分分布を求める変数x ( 2 ), y ( 3 );加算p1 ( & x , & y );乗算m1 ( & x , & p1 );乗算m2 ( & y , & y );加算z ( & m1 , & m2 ); z .評価(); std :: cout << "z = " << z . value << std :: endl ; // 出力: z = 19 z . derive ( 1 ); std :: cout << "∂z/∂x = " << x . partial << ", " << "∂z/∂y = " << y . partial << std :: endl ; // 出力: ∂z/∂x = 7, ∂z/∂y = 8 return 0 ; }
順方向蓄積と逆方向蓄積を超えて
順方向累積と逆方向累積は、連鎖律を通過する 2 つの (極端な) 方法にすぎません。f : R n → R m の完全なヤコビアンを最小の算術演算で計算する問題は、最適 ヤコビアン累積( OJA )問題として知られており、 NP完全です。[10]この証明の中心となるのは、グラフのエッジにラベルを付けるローカル部分の間に代数的な依存関係が存在する可能性があるというアイデアです。特に、2 つ以上のエッジ ラベルが等しいと認識される場合があります。すべてのエッジ ラベルが一意で代数的に独立していると仮定すると、問題の複雑さは依然として未解決のままです。
双数を使った自動微分
順方向モードの自動微分は、実数の代数を拡張して新しい算術式を取得することによって実現されます。すべての数に、その数での関数の導関数を表すための追加の要素が追加され、すべての算術演算子が拡張代数用に拡張されます。拡張代数は、双対数の代数です。
すべての数を数 で置き換えます。ここで、 は実数ですが、 はという特性を持つ抽象数です(無限小。 「滑らかな無限小解析」を参照)。これだけを使用すると、通常の演算では を使用します。
これで、この拡張演算で多項式を計算できるようになりました。 の場合、 はの最初の引数に関する導関数を表し、 はシードと呼ばれ、任意に選択できます。
新しい演算は、 と書かれた要素の順序付きペアで構成され、前述のように、最初の要素には通常の演算が、2 番目の要素には 1 階微分演算が行われます。多項式に関する上記の結果を解析関数に拡張すると、新しい演算に対する基本的な演算といくつかの標準関数のリストが得られます。 一般に、原始関数 に対してとなります。 ここで、と は、それぞれ の最初の引数と 2 番目の引数に関する の 導関数です。
2 項の基本算術演算を混合引数 (ペアと実数)に適用すると、実数は最初に に持ち上げられます。点における関数の導関数は、上記の算術を使用して計算することで求められ、結果として が得られます。
実装
デュアル番号アプローチに基づく実装例を次に示します。
疑似コード
デュアルプラス(デュアルA、デュアルB){
戻る {
実部分(A) + 実部分(B)、
無限小部分(A) + 無限小部分(B)
};
}
デュアルマイナス(デュアルA、デュアルB) {
戻る {
実部分(A) - 実部分(B)、
無限小部分(A) - 無限小部分(B)
};
}
デュアル乗算(デュアルA、デュアルB) {
戻る {
実部分(A) * 実部分(B)、
realPartOf(B) * 無限小PartOf(A) + realPartOf(A) * 無限小PartOf(B)
};
}
0 の場合
y = {y, 0};
イプシロン = {0, 1};
xPartial = infinitesimalPartOf(f(X + イプシロン、Y));
yPartial = infinitesimalPartOf(f(X, Y + イプシロン));
C++
#include <iostream> struct Dual { float realPart , infinitesimalPart ; Dual ( float realPart , float infinitesimalPart = 0 ) : realPart ( realPart ), infinitesimalPart ( infinitesimalPart ) {} Dual operator + ( Dual other ) { return Dual ( realPart + other . realPart , infinitesimalPart + other . infinitesimalPart ); } Dual operator * ( Dual other ) { return Dual ( realPart * other . realPart , other . realPart * infinitesimalPart + realPart * other . infinitesimalPart ); } }; // 例: (x, y) = (2, 3) における z = x * (x + y) + y * y の部分分布を求めるDual f ( Dual x , Dual y ) { return x * ( x + y ) + y * y ; } int main () { Dual x = Dual ( 2 );デュアルy = Dual ( 3 );デュアルイプシロン= Dual ( 0 , 1 );デュアルa = f ( x +イプシロン, y );デュアルb = f ( x , y +イプシロン); std :: cout << "∂z/∂x = " << a . infinitesimalPart << ", " << "∂z/∂y = " << b . infinitesimalPart <<
std :: endl ;
// 出力: ∂z/∂x = 7, ∂z/∂y = 8 return 0 ; }
ベクトル引数と関数
方向微分演算子を採用することで、多変数関数を一変数関数と同じ効率とメカニズムで処理できます。つまり、 を計算するだけで十分な場合、方向におけるの方向微分は、上記と同じ演算を使用してとして計算できます。 のすべての要素が必要な場合は、関数の評価が必要です。多くの最適化アプリケーションでは、方向微分で十分であることに注意してください。
高次かつ多くの変数
上記の演算は、多変数関数の 2 次以上の導関数を計算するために一般化できます。ただし、演算規則はすぐに複雑になります。複雑さは、最高の導関数次数で 2 次になります。代わりに、切り捨てられたテイラー多項式代数を使用できます。一般化された双対数で定義される結果の演算により、関数をデータ型のように使用して効率的に計算できます。関数のテイラー多項式がわかれば、導関数は簡単に抽出できます。
実装
フォワードモード AD は、実数がデュアル数に置き換えられ、定数がゼロのイプシロン係数を持つデュアル数に持ち上げられ、数値プリミティブがデュアル数で動作するように持ち上げられる、プログラムの非標準解釈によって実装されます。この非標準解釈は、通常、ソース コード変換または演算子オーバーロードの 2 つの戦略のいずれかを使用して実装されます。
ソースコード変換 (SCT)

関数のソース コードは、元の命令とインターリーブされた導関数を計算するためのステートメントを含む、自動生成されたソース コードに置き換えられます。
ソースコード変換はすべてのプログラミング言語で実装でき、コンパイラによるコンパイル時の最適化も容易になります。ただし、AD ツール自体の実装は難しく、ビルド システムは複雑になります。
演算子オーバーロード (OO)

演算子のオーバーロードは、それをサポートする言語で記述されたソース コードでは可能です。実数と基本的な数学演算のオブジェクトは、上記に示した拡張演算に対応するためにオーバーロードする必要があります。これにより、関数を差別化するために元のソース コード内の演算の形式やシーケンスを変更する必要はありませんが、オーバーロードをサポートするために数値とベクトルの基本データ型を変更する必要があり、特別なフラグ付け演算の挿入が必要になることもよくあります。各ループに固有の演算子のオーバーロード オーバーヘッドがあるため、このアプローチでは通常、速度パフォーマンスが低下します。
演算子のオーバーロードとソースコード変換
オーバーロードされた演算子を使用して評価グラフを抽出し、実行時にプライマリ関数の AD バージョンを自動的に生成することができます。従来の OO AAD とは異なり、このような AD 関数は反復ごとに変化しません。したがって、Xi サンプルごとに OO またはテープ解釈の実行時のオーバーヘッドが存在します。
AD関数は実行時に生成されるため、プログラムの現在の状態を考慮して特定の値を事前計算するように最適化できます。さらに、ネイティブCPUベクトル化を一貫して利用して、ユーザーデータの4(8)倍のチャンクを処理するように生成することもできます(AVX2\AVX512の速度は4~8倍になります)。マルチスレッドを考慮すると、このようなアプローチは、従来のAADツールと比較して、最終的に8×コアのオーダーの高速化につながります。リファレンス実装はGitHubで入手できます。[11]
参照
注記
参考文献
- ^ Neidinger, Richard D. (2010). 「自動微分化とMATLABオブジェクト指向プログラミング入門」(PDF) . SIAM Review . 52 (3): 545–563. CiteSeerX 10.1.1.362.6580 . doi :10.1137/080743627. S2CID 17134969.
- ^ ab Baydin, Atilim Gunes; Pearlmutter, Barak; Radul , Alexey Andreyevich; Siskind, Jeffrey (2018). 「機械学習における自動微分化:調査」。機械学習研究ジャーナル。18 :1–43。
- ^ ab RE Wengert (1964). 「簡単な自動微分評価プログラム」. Comm. ACM . 7 (8): 463–464. doi : 10.1145/355586.364791 . S2CID 24039274.
- ^ Griewank, Andreas (2012). 「誰が逆微分法を発明したのか?」( PDF )。最適化ストーリー、Documenta Matematica。Documenta Mathematica シリーズ。特別巻 ISMP: 389–400。doi :10.4171/dms/6/38。ISBN 978-3-936609-58-5。
- ^ Linnainmaa, Seppo (1976). 「累積丸め誤差のテイラー展開」BIT 数値数学16 ( 2): 146–160. doi :10.1007/BF01931367. S2CID 122357351.
- ^ Maximilian E. Schüle、Maximilian Springer、Alfons Kemper、Thomas Neumann (2022)。「自動微分化のためのLLVMコード最適化」。エンドツーエンド機械学習のデータ管理に関する第6回ワークショップの議事録。pp. 1–4。doi :10.1145 / 3533028.3533302。ISBN 9781450393751. S2CID 248853034。
{{cite book}}: CS1 maint: multiple names: authors list (link) - ^ Bartholomew-Biggs, Michael; Brown, Steven; Christianson, Bruce; Dixon, Laurence (2000). 「アルゴリズムの自動微分化」. Journal of Computational and Applied Mathematics . 124 (1–2): 171–190. Bibcode :2000JCoAM.124..171B. doi :10.1016/S0377-0427(00)00422-2. hdl : 2299/3010 .
- ^ Maximilian E. Schüle、Harald Lang、Maximilian Springer、Alfons Kemper、Thomas Neumann、Stephan Günnemann (2021)。「GPU 上の SQL を使用したデータベース内機械学習」。第33 回国際科学統計データベース管理会議。pp. 25–36。doi : 10.1145 /3468791.3468840。ISBN 9781450384131. S2CID 235386969。
{{cite book}}: CS1 maint: multiple names: authors list (link) - ^ Maximilian E. Schüle、Harald Lang、Maximilian Springer、Alfons Kemper、Thomas Neumann 、Stephan Günnemann (2022)。「データベース内機械学習のための再帰SQLとGPUサポート」。分散および並列データベース。40 (2–3): 205–259。doi : 10.1007 /s10619-022-07417-7。S2CID 250412395 。
{{cite journal}}: CS1 maint: multiple names: authors list (link) - ^ Naumann, Uwe (2008年4月). 「最適ヤコビアン累積はNP完全である」.数学プログラミング. 112 (2): 427–441. CiteSeerX 10.1.1.320.5665 . doi :10.1007/s10107-006-0042-z. S2CID 30219572.
- ^ 「AADC プロトタイプ ライブラリ」。2022 年 6 月 22 日 – GitHub 経由。
さらに読む
- Rall, Louis B. ( 1981)。自動微分化:テクニックとアプリケーション。コンピュータサイエンスの講義ノート。第 120 巻。Springer。ISBN 978-3-540-10861-0。
- Griewank, Andreas; Walther, Andrea ( 2008). 導関数の評価: アルゴリズム的微分化の原理と手法。応用数学のその他のタイトル。第105 巻 (第 2 版) 。SIAM。doi :10.1137/1.9780898717761。ISBN 978-0-89871-659-7。
- Neidinger, Richard (2010). 「自動微分化と MATLAB オブジェクト指向プログラミング入門」(PDF) . SIAM Review . 52 (3): 545–563. CiteSeerX 10.1.1.362.6580 . doi :10.1137/080743627. S2CID 17134969 . 2013-03-15に取得。
- ナウマン、ウーヴェ (2012)。コンピュータプログラムを差別化する技術。ソフトウェア環境ツール。SIAM。ISBN 978-1-611972-06-1。
- ヘンラード、マーク (2017)。金融におけるアルゴリズムの微分化の説明。金融工学の説明。パルグレイブ・マクミラン。ISBN 978-3-319-53978-2。
外部リンク
- www.autodiff.org、「自動微分について知りたいことすべてへの入門サイト」
- 並列 OpenMP プログラムの自動微分化
- 自動微分、C++ テンプレート、写真測量
- 自動微分、演算子オーバーロードアプローチ
- Webベースのインターフェースを介して、Fortran77、Fortran95、またはCプログラムの解析微分を計算します。Fortranプログラムの自動微分
- Scala での順方向自動微分の説明とサンプルコード 2016-08-03 にWayback Machineでアーカイブされました
- finmath-lib 確率的自動微分、ランダム変数の自動微分 (確率的自動微分法の Java 実装)。
- 随伴アルゴリズム微分化: 較正と暗黙関数定理
- C++ テンプレートベースの自動微分化に関する記事と実装
- 接線ソースからソースへのデバッグ可能な派生
- アルゴリズム微分法による正確な第 1 次および第 2 次ギリシャ数
- GPU アクセラレーション アプリケーションの随伴アルゴリズム微分化
- 計算ファイナンスにおける随伴法 アルゴリズム微分化のためのソフトウェアツールサポートop
- Intel Xeon スケーラブル プロセッサーにより xVA 価格計算が 1,000 倍以上高速化
- 高階導関数の VBIC95 例によるスパース切断テイラー級数の実装
