学习笔记:用torch求导的基础

自动求导,初始化向量

torch为隐式构造求导,tensorflow为显式构造

import torch

x = torch.arange(4.0)
x

tensor([0., 1., 2., 3.])

通过一个y=f(x)的函数来讨论问题:

存储梯度

在我们计算y关于ⅹ的梯度之前,我们需要一个地销来存储梯度。

  1. 梯度:梯度是指损失函数相对于模型参数的偏导数。计算梯度是进行梯度下降或其他优化算法以更新模型参数的基础。

  2. .requires_grad_() 方法:这是PyTorch中Tensor的一个方法,用于标记该Tensor在后续的运算中是否需要记录其运算过程以便计算梯度。
    调用 x.requires_grad_(True) 意味着任何基于 x 的计算,PyTorch将会自动记录这些计算步骤,从而在后续可以计算梯度。

  3. .grad 属性:这是一个Tensor,用于存储关于当前Tensor的梯度值。
    默认情况下(即未调用 .requires_grad_() 或在创建Tensor时未指定 requires_grad=True),.grad 是 None。
    只有在进行了前向传播并调用了反向传播(如通过 loss.backward())后,
    .grad 才会被填充上实际的梯度值。

计算x

x.requires_grad_(True) #等价x = torch.arange(4.0,requires_gard(True))
x.grad #默认是none

预期输出值:tensor([0., 1., 2., 3.])

x.requires_grad_(True) #等价x = torch.arange(4.0,requires_gard(True))
x.grad #默认是none

计算y

torch.dot() 只适用于一维张量(即向量)
torch.dot(x, y) 函数用于计算两个张量 x 和 y 的点积(也称为标量积)
x1y1 + x2y2 +…+ xn * yn

.requires_grad属性被设置为了True,你将会看到grad_fn字段出现在输出中。
grad_fn代表了生成当前Tensor的运算的梯度函数(gradient function)
MulBackward0表示该Tensor是作为乘法运算的输出,而Backward0部分指示了这是一个乘法运算的反向传播函数。
在PyTorch的自动微分机制中,每个运算都会有一个正向传播(forward pass)
和一个可能的反向传播(backward pass,用于计算梯度)。

y = 2 * torch.dot(x ,x)
y

预期输出值:tensor(28., grad_fn=)

反向传播

通过调用反向传播函数来自动计算y关于x每个分量的梯度

y.backward() #进行求导
x.grad #访问结果

预期输出值:tensor([ 0., 4., 8., 12.])

再次对比结果

x.grad ==4 * x #y为x的二次函数,对x求导后为4*x

预期输出值:tensor([True, True, True, True])

计算x的另一个函数

在默认情况下,PyTorch会累积梯度,我们需要清除之前的值

x.grad.zero_() #torch内下划线表示重写内容,这里重写为0
y = x.sum()
y.backward()
x.grad
# y 是 x 中所有元素的和,所以 y 对每个 x_i 的偏导数实际上是1
#(不论 x_i 的值是多少,总和对某一项的导数就是1,因为每项都直接加到了总和上)

预期输出值:tensor([1., 1., 1., 1.])

计算的偏导数

深度学习中,我们的目的不是计算微分矩阵,而是批量中每个样本单独计算的偏导数之和。
对非标量调用‘backward`需要传入一个’gradient‘参数,该参数指定微分函数

x.grad.zero_()
y = x * x #此时y为向量

#等价于y.backward(torch.ones(len(x)))
#大部分使用标量求导,所以将y求和
y.sum().backward()
x.grad

预期输出值:tensor([0., 2., 4., 6.])

将某些计算移动到记录的计算图之外

x.grad.zero_()
y = x * x
u = y.detach() #将y当作常数
z = u * x

z.sum().backward()
x.grad == u #作为常数后,求导只剩下u

预期输出值:tensor([True, True, True, True])

重复验证

x.grad.zero_()
y.sum().backward()
x.grad == 2 * x

预期输出值:tensor([True, True, True, True])

计算梯度

即使构建函数的计算图需要通过Python控制流(例如条件”循
环或任意函数调用),我们仍然可以计算得到的变量的梯度

def f(a):
    b = a * 2
    while b.norm() < 1000:
        b = b * 2
    if b.sum() > 0:
        c = b
    else:
        c = 100 * b
    return c

a = torch.randn(size=(), requires_grad=True) 
#torch.randn()生成张量,生成size=():为标量,
#requires_grad对这个张量进行的所有操作都将被记录下来,以便在后续可以通过自动微分
d = f(a)
d.backward()

a.grad == d/a

预期输出值:tensor(True)

博客内容均系原创,未经允许严禁转载!
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇