Skip to content

Commit c306d5d

Browse files
committed
20241025 grad-tensors-intro
1 parent 1d7febe commit c306d5d

6 files changed

+121
-10
lines changed

_posts/2024-09-04-deep-learning-2024autumn-01.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
title: 深度学习课程笔记(一):基础知识
33
author: me
44
date: 2024-09-04 23:00:00 +0800
5-
categories: [Machine Learning, Basic]
6-
tags: [machine learning, deep learning, python]
5+
categories: [Deep Learning, Basic]
6+
tags: [Deep Learning, Python]
77
math: true
88
---
99

_posts/2024-09-04-deep-learning-2024autumn-02.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
title: 深度学习课程笔记(二):PyTorch入门
33
author: me
44
date: 2024-09-04 23:10:00 +0800
5-
categories: [Machine Learning, Basic]
6-
tags: [machine learning, deep learning, python]
5+
categories: [Deep Learning, Basic]
6+
tags: [Deep learning, Python, PyTorch]
77
math: true
88
---
99

_posts/2024-09-04-deep-learning-2024autumn-03.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
title: 深度学习课程笔记(三):前馈神经网络
33
author: me
44
date: 2024-09-04 23:20:00 +0800
5-
categories: [Machine Learning, Basic]
6-
tags: [machine learning, deep learning, python]
5+
categories: [Deep Learning, Basic]
6+
tags: [Deep Learning, Python]
77
math: true
88
---
99

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
---
2+
title: backward 操作时 grad_tensors 参数的作用
3+
author: me
4+
date: 2024-10-25 20:45:00 +0800
5+
categories: [Deep Learning, PyTorch]
6+
tags: [Deep Learning, PyTorch, Gradient]
7+
math: true
8+
---
9+
10+
## 问题提出
11+
12+
在阅读 Dive Into Deep Learning 时,我在 [ReLU激活函数部分](https://zh-v2.d2l.ai/chapter_multilayer-perceptrons/mlp.html#relu) 看到这样一段代码:
13+
14+
```python
15+
import torch
16+
x = torch.arange(-8.0, 8.0, 0.1, requires_grad=True)
17+
y = torch.relu(x)
18+
y.backward(torch.ones_like(x), retain_graph=True)
19+
```
20+
21+
其中在对非标量张量 y 进行梯度计算时,引入了参数 `(grad_tensors=)torch.ones_like(x)`。如果不加入这个参数,在运行时则会报错:
22+
23+
```python
24+
x = torch.tensor([1.0, 2.0, 3.0], requires_grad=True)
25+
y = x*x
26+
y.backward()
27+
```
28+
29+
```text
30+
RuntimeError: grad can be implicitly created only for scalar outputs
31+
```
32+
33+
证明在计算非标量张量对张量的梯度时,必须引入 `grad_tensors` 这一参数。但是为什么要引入这一参数?这个参数是如何参与到梯度计算中的?
34+
35+
阅读 [torch.autograd.backward 文档](https://pytorch.org/docs/stable/generated/torch.autograd.backward.html),发现 PyTorch 这样解释计算非标量张量对张量的梯度的原理:
36+
37+
>The graph is differentiated using the chain rule. If any of `tensors` are non-scalar (i.e. their data has more than one element) and require gradient, then the Jacobian-vector product would be computed, in this case the function additionally requires specifying `grad_tensors`. It should be a sequence of matching length, that contains the “vector” in the Jacobian-vector product, usually the gradient of the differentiated function w.r.t. corresponding tensors (`None` is an acceptable value for all tensors that don’t need gradient tensors).
38+
>
39+
>该(计算)图使用链式法则进行微分。如果任何`tensors`是非标量(即它们的数据具有多个元素)并且需要梯度,则将计算雅可比向量积,在这种情况下,该函数还需要指定`grad_tensors` 。它应该是一个匹配长度的序列,包含雅可比向量乘积中的“向量”,通常是对应张量的微分函数的梯度(对于所有不需要梯度张量的张量来说, `None`是可接受的值)。
40+
41+
## 背景知识:雅可比矩阵
42+
43+
在一般的梯度计算中,如果要计算矩阵对矩阵的梯度,会借助雅各比矩阵来进行。例如,假设我们有一个函数 $$f(x)$$,其中:
44+
- 输入张量 $$x$$ 的形状为 $$[p]$$
45+
- 输出张量 $$y = f(x)$$ 的形状为 $$[n]$$
46+
47+
那么,$$y$$$$x$$ 的雅可比矩阵 $$J$$ 的维度是 $$[n, p]$$。这表示 $$y$$ 中的每个元素 $$y_{i}$$$$x$$ 的偏导数 $$\frac{\partial y_{i}}{\partial x_k}$$ 构成了雅可比矩阵的元素 $$J_{i,k}$$。在这个雅可比矩阵中,张量 $$x$$ 的每个元素都对应了 $$n$$ 个梯度值。
48+
49+
$$
50+
J = \begin{bmatrix}
51+
\frac{\partial y_1}{\partial x_1} & \frac{\partial y_1}{\partial x_2} & \cdots & \frac{\partial y_1}{\partial x_p} \\
52+
\frac{\partial y_2}{\partial x_1} & \frac{\partial y_2}{\partial x_2} & \cdots & \frac{\partial y_2}{\partial x_p} \\
53+
\vdots & \vdots & \ddots & \vdots \\
54+
\frac{\partial y_n}{\partial x_1} & \frac{\partial y_n}{\partial x_2} & \cdots & \frac{\partial y_n}{\partial x_p}
55+
\end{bmatrix}
56+
$$
57+
58+
但这样做存在一些问题:
59+
60+
1. 没有定义如何将每个 $$x_i$$ 的若干梯度值计算为单个梯度
61+
2. 计算这么大的雅可比矩阵会消耗较大的内存和计算量。
62+
63+
所以在计算非标量张量对非标量张量的梯度时,PyTorch 不会直接计算雅可比矩阵(Jacobian Matrix),而是通过 `grad_tensors` 实现了对雅可比向量积的高效计算。这不仅节省内存和计算量,而且满足大多数深度学习应用的需求。
64+
65+
## 背景知识:雅可比向量积
66+
67+
**雅可比向量积**(JVP)则是将雅可比矩阵 $$J$$ 与一个向量 $$v$$ 相乘,即:
68+
69+
$$
70+
J \cdot v
71+
$$
72+
73+
其中 $$v$$ 的维度与 $$y$$ 相同。这一操作的结果是一个与 $$x$$ 相同维度的向量,即输出张量的加权导数之和。通过计算雅可比向量积,而不是完整的雅可比矩阵,我们可以避免计算和存储所有的偏导数。
74+
75+
$$
76+
J \cdot v = \begin{pmatrix}
77+
\frac{\partial y_1}{\partial x_1} & \cdots & \frac{\partial y_n}{\partial x_1} \\
78+
\vdots & \ddots & \vdots \\
79+
\frac{\partial y_1}{\partial x_p} & \cdots & \frac{\partial y_n}{\partial x_p}
80+
\end{pmatrix}
81+
\begin{pmatrix}
82+
\frac{\partial l}{\partial y_1} \\
83+
\vdots \\
84+
\frac{\partial l}{\partial y_n}
85+
\end{pmatrix}
86+
= \begin{pmatrix}
87+
\frac{\partial l}{\partial x_1} \\
88+
\vdots \\
89+
\frac{\partial l}{\partial x_p}
90+
\end{pmatrix}
91+
$$
92+
93+
## grad_tensors 和雅可比向量积的关系
94+
95+
在 PyTorch 中,`grad_tensors` 参数实际上就是充当这个向量 $$v$$ 的角色。在计算梯度时,如果我们传入了 `grad_tensors`,则 PyTorch 计算的梯度实际上是雅可比矩阵 $$J$$`grad_tensors` 的向量积 $$J \cdot \text{grad\_tensors}$$,也就是:
96+
97+
$$
98+
\frac{\partial (y \cdot \text{grad\_tensors}^{\mathrm T})}{\partial x}
99+
$$
100+
101+
这种方式高效地计算了雅可比向量积,而不是直接计算整个雅可比矩阵,从而避免了显式存储和计算高维的雅可比矩阵。
102+
103+
## 总结
104+
105+
通过使用 `grad_tensors`,PyTorch 可以高效地计算非标量张量对输入的梯度。其核心思想是利用雅可比向量积来避免显式构造雅可比矩阵,从而在内存和计算上实现了极大的优化。这种方式在深度学习中尤为有用,因为直接构造和存储高维雅可比矩阵不仅昂贵且不切实际。
106+
107+
## References
108+
109+
1. [torch.autograd.backward - PyTorch Docs](https://pytorch.org/docs/stable/generated/torch.autograd.backward.html)
110+
2. [Pytorch autograd,backward详解](https://zhuanlan.zhihu.com/p/83172023)
111+
3. [我的 ChatGPT 提问过程](https://chatgpt.com/share/671b5b97-bd64-8007-a484-4394ed518190)

_posts/2024-5-10-use-of-dataloader-and-dataset.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
title: 理解 PyTorch 中 DataLoader 与 Dataset 的使用
33
author: me
44
date: 2024-05-10 22:00:00 +0800
5-
categories: [Machine Learning, PyTorch]
6-
tags: [machine learning, deep learning, data processing, python, pytorch, dataloader, dataset]
5+
categories: [Deep Learning, PyTorch]
6+
tags: [Deep learning, Data Processing, Python, PyTorch, DataLoader, Dataset]
77
---
88

99
为了提高代码的可读性与模块化特性,我们希望数据集代码与模型训练代码分离。于是 PyTorch 提供了两个原始类型(Data Primitive):`torch.utils.data.DataLoader``torch.utils.data.Dataset`,分别用于定义数据集对象、迭代读取数据条目。

_posts/2024-7-31-deep-learning-note-caolvchong.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
title: 深度学习笔记:“草履虫都能看懂”教程
33
author: me
44
date: 2024-07-31 00:00:00 +0800
5-
categories: [Machine Learning, Basic]
6-
tags: [machine learning, deep learning, python]
5+
categories: [Deep Learning, Basic]
6+
tags: [Deep Learning, Python]
77
math: true
88
---
99

0 commit comments

Comments
 (0)