Skip to content

Commit

Permalink
Merge pull request chenzomi12#282 from GG-yuki/patch-2
Browse files Browse the repository at this point in the history
Update 06ReversedMode.md
  • Loading branch information
chenzomi12 authored Sep 29, 2024
2 parents 1b2ca0f + 458388a commit 846da0b
Showing 1 changed file with 7 additions and 7 deletions.
14 changes: 7 additions & 7 deletions 05Framework/02AutoDiff/06ReversedMode.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<!--适用于[License](https://github.com/chenzomi12/AISystem/blob/main/LICENSE)版权许可-->

# 动手实现 PyTroch 微分
# 动手实现 PyTorch 微分

这里记录一下使用操作符重载(OO)编程方式的自动微分,其中数学实现模式则是使用反向模式(Reverse Mode),综合起来就叫做反向 OO 实现 AD 啦。

## 基础知识

下面一起来回顾一下操作符重载和反向模式的一些基本概念,然后一起去尝试着用 Python 去实现 PyTroch 这个 AI 框架中最核心的自动微分机制是如何实现的。
下面一起来回顾一下操作符重载和反向模式的一些基本概念,然后一起去尝试着用 Python 去实现 PyTorch 这个 AI 框架中最核心的自动微分机制是如何实现的。

### 操作符重载 OO

Expand All @@ -16,7 +16,7 @@

在 C++ 中使用运算符重载实现的流行工具是 ADOL-C(Walther 和 Griewank,2012)。ADOL-C 要求对变量使用启用 AD 的类型,并在 Tape 数据结构中记录变量的算术运算,随后可以在反向模式 AD 计算期间“回放”。Mxyzptlk 库 (Michelotti, 1990) 是 C++ 能够通过前向传播计算任意阶偏导数的另一个例子。

FADBAD++ 库(Bendtsen 和 Stauning,1996 年)使用模板和运算符重载为 C++ 实现自动微分。对于 Python 语言来说,autograd 提供正向和反向模式自动微分,支持高阶导数。在机器学习 ML 或者深度学习 DL 领域,目前 AI 框架中使用操作符重载 OO 的一个典型代表是 PyTroch,其中使用数据结构 Tape 来记录计算流程,在反向模式求解梯度的过程中进行 replay Operator。
FADBAD++ 库(Bendtsen 和 Stauning,1996 年)使用模板和运算符重载为 C++ 实现自动微分。对于 Python 语言来说,autograd 提供正向和反向模式自动微分,支持高阶导数。在机器学习 ML 或者深度学习 DL 领域,目前 AI 框架中使用操作符重载 OO 的一个典型代表是 PyTorch,其中使用数据结构 Tape 来记录计算流程,在反向模式求解梯度的过程中进行 replay Operator。

下面总结一下操作符重载的一个基本流程:

Expand All @@ -39,7 +39,7 @@ FADBAD++ 库(Bendtsen 和 Stauning,1996 年)使用模板和运算符重载

反向自动微分同样是基于链式法则。仅需要一个前向过程和反向过程,就可以计算所有参数的导数或者梯度。因为需要结合前向和后向两个过程,因此反向自动微分会使用一个特殊的数据结构,来存储计算过程。

而这个特殊的数据结构例如 TensorFlow 或者 MindSpore,则是把所有的操作以一张图的方式存储下来,这张图可以是一个有向无环(DAG)的计算图;而 PyTroch 则是使用 Tape 来记录每一个操作,他们都表达了函数和变量的关系。
而这个特殊的数据结构例如 TensorFlow 或者 MindSpore,则是把所有的操作以一张图的方式存储下来,这张图可以是一个有向无环(DAG)的计算图;而 PyTorch 则是使用 Tape 来记录每一个操作,他们都表达了函数和变量的关系。

反向模式根据从后向前计算,依次得到对每个中间变量节点的偏导数,直到到达自变量节点处,这样就得到了每个输入的偏导数。在每个节点处,根据该节点的后续节点(前向传播中的后续节点)计算其导数值。

Expand All @@ -64,7 +64,7 @@ $$ \frac{\partial f}{\partial x}=\sum_{k=1}^{N} \frac{\partial f}{\partial v_{k}

## 反向操作符重载实现

下面的代码主要介绍反向模式自动微分的实现。目的是通过了解 PyTroch 的 auto diff 实现,来了解到上面复杂的反向操作符重载实现自动微分的原理,值的主要的是千万不要在乎这是 MindSpore 的实现还是 TensorFlow 版的实现(实际上都不是哈)。
下面的代码主要介绍反向模式自动微分的实现。目的是通过了解 PyTorch 的 auto diff 实现,来了解到上面复杂的反向操作符重载实现自动微分的原理,值的主要的是千万不要在乎这是 MindSpore 的实现还是 TensorFlow 版的实现(实际上都不是哈)。

首先,需要通过 typing 库导入一些辅助函数。

Expand All @@ -81,7 +81,7 @@ def fresh_name():

`fresh_name` 用于打印跟 `tape` 相关的变量,并用 `_name` 来记录是第几个变量。

为了能够更好滴理解反向模式自动微分的实现,实现代码过程中不依赖 PyTroch 的 autograd。代码中添加了变量类 `Variable` 来跟踪计算梯度,并添加了梯度函数 `grad()` 来计算梯度。
为了能够更好滴理解反向模式自动微分的实现,实现代码过程中不依赖 PyTorch 的 autograd。代码中添加了变量类 `Variable` 来跟踪计算梯度,并添加了梯度函数 `grad()` 来计算梯度。

对于标量损失 l 来说,程序中计算的每个张量 x 的值,都会计算值 dl/dX。反向模式从 dl/dl=1 开始,使用偏导数和链式规则向后传播导数,例如:

Expand Down Expand Up @@ -336,7 +336,7 @@ print("dy", dy)

## 小结与思考

- 通过 Python 语言的操作符重载技术,展示了如何实现一个基础的反向自动微分(AD)机制,模仿了 PyTroch 等 AI 框架中的自动微分系统。
- 通过 Python 语言的操作符重载技术,展示了如何实现一个基础的反向自动微分(AD)机制,模仿了 PyTorch 等 AI 框架中的自动微分系统。

- 实现中定义了 Variable 类来跟踪计算梯度,并通过 Tape 数据结构记录计算过程,最终通过反向传播计算出梯度,验证了反向操作符重载实现自动微分的基本原理和效果。

Expand Down

0 comments on commit 846da0b

Please sign in to comment.