目录
一、实验介绍
PyTorch提供了自动求导机制,它是PyTorch的核心功能之一,用于计算梯度并进行反向传播。自动求导机制使得深度学习中的梯度计算变得更加简单和高效。
二、实验环境
本系列实验使用了PyTorch深度学习框架,相关操作如下:
1. 配置虚拟环境
conda create -n DL python=3.7
conda activate DL
pip install torch==1.8.1+cu102 torchvision==0.9.1+cu102 torchaudio==0.8.1 -f https://download.pytorch.org/whl/torch_stable.html
conda install matplotlib
conda install scikit-learn
2. 库版本介绍
软件包 | 本实验版本 | 目前最新版 |
matplotlib | 3.5.3 | 3.8.0 |
numpy | 1.21.6 | 1.26.0 |
python | 3.7.16 | |
scikit-learn | 0.22.1 | 1.3.0 |
torch | 1.8.1+cu102 | 2.0.1 |
torchaudio | 0.8.1 | 2.0.2 |
torchvision | 0.9.1+cu102 | 0.15.2 |
三、实验内容
ChatGPT:
本系列为实验内容,对理论知识不进行详细阐释
(咳咳,其实是没时间整理,待有缘之时,回来填坑)
0. 导入必要的工具包
import torch
1. 标量求导
对只有一个输出值的函数进行求导,结果是一个标量值。
# 最简单的情况,X是一个标量
x = torch.tensor(2, dtype=torch.float32, requires_grad=True)
y = x ** 2 + 4 * x
print(x.grad)
y.backward()
print(x.grad)
-
创建一个名为
x
的张量,其值为2,数据类型为float32
,并设置requires_grad
为True
以启用自动求导功能。 -
y = x ** 2 + 4 * x
:定义一个新的张量y
,其值为x
的平方加上4乘以x
。 -
在调用
backward()
函数之前,打印x
的梯度值。由于还没有进行反向传播,x.grad
的值为None
。 -
通过调用
backward()
函数,计算y
相对于所有需要梯度的张量的梯度。在这种情况下,只有x
需要梯度,因此x.grad
将被计算。 -
在调用
backward()
函数之后,打印x
的梯度值,即导数。由于y
是关于x
的函数,并且我们通过backward()
函数进行了反向传播,所以x.grad
现在将包含y
相对于x
的导数值。
输出:
None
tensor(8.)
2. 矩阵求导
对具有多个输出值的函数进行求导,结果是一个矩阵或向量。
x = torch.ones(2, 2, requires_grad=True)
print(x.grad)
# y是一个矩阵
y = x ** 2 + 4 * x
y.backward(torch.ones(2, 2))
print(x.grad)
-
创建一个2x2的张量
x
,其所有元素的值都为1,并设置requires_grad
为True
以启用自动求导功能。 -
在调用
backward()
函数之前,打印x
的梯度值。由于还没有进行反向传播,x.grad
的值为None
。 -
定义一个新的张量
y
,其值为x
的每个元素的平方加上4乘以x
的每个元素。由于x
的形状为2x2,因此y
也将具有相同的形状。 -
y.backward(torch.ones(2, 2))
:通过调用backward()
函数,计算y
相对于所有需要梯度的张量的梯度。在这种情况下,只有x
需要梯度,torch.ones(2, 2)
表示将梯度初始化为2x2的全1矩阵。 -
print(x.grad)
:打印x
的梯度值,即导数。由于y
是关于x
的函数,并且我们通过backward()
函数进行了反向传播,所以x.grad
将包含y
相对于x
的导数值
输出:
None
tensor([[6., 6.],
[6., 6.]])
x = torch.ones(2, 2, requires_grad=True)
# y是一个矩阵
y = x ** 2 + 4 * x
y.backward(torch.ones(2, 2))
print(x.grad)
u = x ** 3 + 2 * x
# z是一个标量
z = u.sum()
z.backward()
print(x.grad)
-
u = x ** 3 + 2 * x
:定义一个新的张量u
,其值为x
的每个元素的立方加上2乘以x
的每个元素。由于x
的形状为2x2,因此u
也将具有相同的形状。 -
z = u.sum()
:定义一个新的标量z
,其值为u
所有元素的总和。sum()
函数将u
中的所有元素相加得到一个标量值。 -
z.backward()
:通过调用backward()
函数,计算z
相对于所有需要梯度的张量的梯度。在这种情况下,只有x
需要梯度,因为u
是关于x
的函数。 -
print(x.grad)
:打印x
的梯度值,即导数。由于z
是关于x
的函数,并且我们通过backward()
函数进行了反向传播,所以x.grad
将包含z
相对于x
的导数值。
输出:
tensor([[6., 6.],
[6., 6.]])
tensor([[11., 11.],
[11., 11.]])
3. 计算图
import torch
x = torch.tensor(2.0, requires_grad=True)
y = torch.tensor(3.0, requires_grad=True)
z = x**2 + y**3
z.backward()
print("Gradient of x:", x.grad)
print("Gradient of y:", y.grad)
输出:
Gradient of x: tensor(4.)
Gradient of y: tensor(27.)