<aside> <img src="/icons/condense_yellow.svg" alt="/icons/condense_yellow.svg" width="40px" /> Python | C++ | 漂移扩散 | 方程 | 公式 | 期权 | 套利 | 定价权 | 算法 | 正向累积 | 反向累积 | 回归 | 分类 | 生成对抗网络 | 几何 | 网格

</aside>

🎯要点

🎯漂移扩散方程计算微分 | 🎯期权无风险套利公式计算微分 | 🎯实现图结构算法微分 | 🎯实现简单正向和反向计算微分 | 🎯实现简单回归分类和生成对抗网络计算微分 | 🎯几何网格计算微分

pie showdata
 title 语言分比
 "Python":42
 "C++":38
 "CMake":20

✂️梗概

🍇Python和C++计算微分正反向累积

算法微分在机器学习领域尤为重要。例如,它允许人们在神经网络中实现反向传播,而无需手动计算导数。

计算微分的基础是复合函数偏导数链式法则提供的微分分解。简单结构如:

$$ \begin{aligned} y & =f(g(h(x)))=f\left(g\left(h\left(w_0\right)\right)\right)=f\left(g\left(w_1\right)\right)=f\left(w_2\right)=w_3 \\ w_0 & =x \\ w_1 & =h\left(w_0\right) \\ w_2 & =g\left(w_1\right) \\ w_3 & =f\left(w_2\right)=y \end{aligned} $$

由链式法则得出:

$$ \frac{\partial y}{\partial x}=\frac{\partial y}{\partial w_2} \frac{\partial w_2}{\partial w_1} \frac{\partial w_1}{\partial x}=\frac{\partial f\left(w_2\right)}{\partial w_2} \frac{\partial g\left(w_1\right)}{\partial w_1} \frac{\partial h\left(w_0\right)}{\partial x} $$

通常,存在两种不同的计算微分模式:正向累积和反向累积。

正向累积指定从内到外遍历链式法则(即首先计算 $\partial w_1 / \partial x$,然后计算 $\partial w_2 / \partial w_1$,最后计算 $\partial y / \partial w_2$ ),而反向累积是从外到内的遍历(首先计算 $\partial y / \partial w_2$,然后计算 $\partial w_2 / \partial w_1$,最后计算 $\partial w_1 / \partial x$)。更简洁地说,

正向累积计算递归关系:$\frac{\partial w_i}{\partial x}=\frac{\partial w_i}{\partial w_{i-1}} \frac{\partial w_{i-1}}{\partial x}$ 且$w_3=y$

反向累积计算递归关系:$\frac{\partial y}{\partial w_i}=\frac{\partial y}{\partial w_{i+1}} \frac{\partial w_{i+1}}{\partial w_i}$ 且 $w_0=x$

正向累积在一次传递中计算函数和导数(但每个仅针对一个独立变量)。相关方法调用期望表达式 Z 相对于变量 V 导出。该方法返回一对已求值的函数及其导数。该方法递归遍历表达式树,直到到达变量。如果请求相对于此变量的导数,则其导数为 1,否则为 0。然后求偏函数以及偏导数。

伪代码:

 tuple<float,float> evaluateAndDerive(Expression Z, Variable V) {
    if isVariable(Z)
       if (Z = V) return {valueOf(Z), 1};
       else return {valueOf(Z), 0};
    else if (Z = A + B)
       {a, a'} = evaluateAndDerive(A, V);
       {b, b'} = evaluateAndDerive(B, V);
       return {a + b, a' + b'};
    else if (Z = A - B)
       {a, a'} = evaluateAndDerive(A, V);
       {b, b'} = evaluateAndDerive(B, V);
       return {a - b, a' - b'};
    else if (Z = A * B)
       {a, a'} = evaluateAndDerive(A, V);
       {b, b'} = evaluateAndDerive(B, V);
       return {a * b, b * a' + a * b'};
 }

Python实现正向累积:

 class ValueAndPartial:
     def __init__(self, value, partial):
         self.value = value
         self.partial = partial
 
     def toList(self):
         return [self.value, self.partial]
 
 class Expression:
     def __add__(self, other):
         return Plus(self, other)
 
     def __mul__(self, other):
         return Multiply(self, other)
 
 class Variable(Expression):
     def __init__(self, value):
         self.value = value
 
     def evaluateAndDerive(self, variable):
         partial = 1 if self == variable else 0
         return ValueAndPartial(self.value, partial)
 
 class Plus(Expression):
     def __init__(self, expressionA, expressionB):
         self.expressionA = expressionA
         self.expressionB = expressionB
 
     def evaluateAndDerive(self, variable):
         valueA, partialA = self.expressionA.evaluateAndDerive(variable).toList()
         valueB, partialB = self.expressionB.evaluateAndDerive(variable).toList()
         return ValueAndPartial(valueA + valueB, partialA + partialB)
 
 class Multiply(Expression):
     def __init__(self, expressionA, expressionB):
         self.expressionA = expressionA
         self.expressionB = expressionB
 
     def evaluateAndDerive(self, variable):
         valueA, partialA = self.expressionA.evaluateAndDerive(variable).toList()
         valueB, partialB = self.expressionB.evaluateAndDerive(variable).toList()
         return ValueAndPartial(valueA * valueB, valueB * partialA + valueA * partialB)
 
 # Example: Finding the partials of z = x * (x + y) + y * y at (x, y) = (2, 3)
 x = Variable(2)
 y = Variable(3)
 z = x * (x + y) + y * y
 xPartial = z.evaluateAndDerive(x).partial
 yPartial = z.evaluateAndDerive(y).partial
 print("∂z/∂x =", xPartial)  # Output: ∂z/∂x = 7
 print("∂z/∂y =", yPartial)  # Output: ∂z/∂y = 8