算法微分是如何工作的,它可以應用在哪裡?
標題說明了一切,但讓我擴展一下。算法微分似乎是一種允許程序/編譯器確定函式的導數的方法。我想它是優化之類的一個很好的工具,因為如果我們知道成本函式及其導數,其中許多算法會更好地工作。
我知道算法微分與數值微分不同,因為導數不精確。但它是否與符號微分相同,例如在 SymPy、Matlab 或 Mathematica 中實現的?
第二,量化金融到底能用在哪裡?我提到了優化,所以我想到了校準。希臘人也是一種自然的應用,因為它們在定義上是衍生品,但在蒙地卡羅的情況下如何運作?還有其他應用嗎?
自動微分(又名 AD)是一系列用於評估編碼函式的導數的方法。這些方法比有限差分精確得多,因為它們在沒有浮點舍入誤差的情況下理論上是精確的。
然而,AD 與符號分化略有不同。這裡的關鍵區別在於電腦代數係統(如 Mathematica)將返回一個可以計算導數的函式。然而,在自動微分的許多實現中,導數被計算為評估原始函式的副作用。
有許多不同的方式來實現 AD,它們在維基百科頁面上以合理的數量進行了概述。
<https://en.wikipedia.org/wiki/Automatic_differentiation>
簡單的實現方法
也許實現 AD 最直接的方法是使用“雙數”和運算符重載。關鍵思想是引入一種新型的標量數,稱為對偶數。對偶數通過將每個數 $x$ 替換為 $x + x’ \epsilon$ 來擴充實數的代數,其中 $\epsilon$ 具有屬性 $\epsilon^2 = 0$。
使用它,您可以定義對偶數的代數,如您所料:
\begin{align} (u+u’\epsilon) + (v + v’\epsilon) &= (u+v) + (u’ + v’)\epsilon \ (u+u’\epsilon) - (v + v’\epsilon) &= (uv) + (u’ - v’)\epsilon \ (u+u’\epsilon) * (v+v’\epsilon) &= (uv) + (uv ’ + vu’)\epsilon \ (u + u’\epsilon) / (v+v’\epsilon) &= (u/v) + \frac{u’v - uv’}{v^2}\ ε \end{對齊}
請參閱 wikipedia 頁面了解此功能對其他功能的擴展($\sin$、$\cos$、$\exp$、…)
精明的讀者會注意到,對偶數之間的任何運算結果的 $\epsilon$ 分量都實現了該運算的鍊式規則。因此,任何操作序列(即編碼函式)將同時計算函式值及其導數。使用這種方法導致的唯一精度損失是浮點舍入誤差(因此您仍然需要使用數值穩定的算法)。
在軟體方面,主要負擔是雙數類的實現以及重載您想要使用的任何運算符/函式。此外,您希望區分的任何函式都應該(用 C++ 術語)在輸入類型上進行模板化。例如,而不是:
double f(double x) { ... }
你會寫
template<typename T> T f(T x) {...}
這樣做將允許您重新使用相同的程式碼來執行正常的函式呼叫或執行 AD 函式呼叫。
範常式式碼
這是我在有限元庫中使用的方法的 C++ 實現的連結。如果您願意,可以免費獲取/使用/修改程式碼。您必須去掉非標準標頭和命名空間打開/關閉行,但它不應該與庫的其餘部分有任何依賴關係。
<https://github.com/tjolsen/YAFEL/blob/master/include/utils/DualNumber.hpp>
最後的想法
這裡描述的想法可以推廣到向量值輸入/輸出。通過這樣做,您可以計算雅可比矩陣,而不必推導每個偏導數應該是什麼。根據輸入和輸出的維度,此處描述的雙數方法以外的其他方法可能更有效,因此值得更詳細地閱讀。