什么是梯度?
- 在一元函数中,某点的梯度标的就说某点的导数. 在多元函数中某点的梯度表示的是由每个自变量所对应的偏导数所组成的向量
- 在前面的线性回归中 就像
y = wx + b
方程中求出w参数最优的解,就需要对w参数进行偏导数的求取,然后通过偏导数的值来调整w参数以便找到最优解。
自动计算梯度和偏导数
-
在PyTorch中可以使用
torch.autograd.backward()
方法来自动计算梯度 -
在定义张量时,可以指定
requires_grad=True
表示这个张量可以求偏导数
import torch
# 随机出张量x 指定可以计算偏导数
x = torch.randn(1,requires_grad=True)
# y和z张量不可以求偏导
y = torch.randn(1)
z = torch.randn(1)
# f1中有张量允许求偏导
f1 = 2*x + y
# f2中没有张量可以允许求偏导
f2 = y + z
# 打印两个方程的梯度
print(f1.grad_fn)
print(f2.grad_fn)
得出结论:
- f1中有允许可以求偏导的张量存在才可以求梯度
grad_fn为梯度
1. 求x的偏导数
# 可以求梯度的变量先使用backward()反向传播
f1.backward()
# 使用张量的grad属性拿到偏导数的值
x.grad
2. 停止梯度的计算
张量.requires_grad_(False)
# 创建张量 指定可以求偏导
a = torch.randn(2,2,requires_grad=True)
# a对应的b变量
b = ((a * 3)/(a - 1))
# 查看梯度
print(b.grad_fn)
# 停止a张量可以求偏导
a.requires_grad_(False)
# 再次指定b对应变量
b = ((a * 3) / (a - 1))
# 为None了
print(b.grad_fn)
3. 获取到可以求偏导数的张量相同的内容,但是新变量不可以求偏导
张量.detach()方法
a = torch.randn(2,2,requires_grad=True)
# 可以求偏导的张量返回一个相同的张量但是不可以求偏导数
b = a.detach()
print(a.requires_grad)
print(b.requires_grad)
4. 在作用域中张量不可计算偏导数
with torch.no_grad(): 内的整个作用域
a = torch.randn(2, 2, requires_grad=True)
print((a ** 2).requires_grad)
with torch.no_grad():
print((a ** 2).requires_grad)
梯度的清空
- 在PyTorch中,如果我们利用
torch.autograd.backward()方法
求解张量的梯度, 在多次运行该函数的情况下, 该函数会将计算得到的梯度累加起来。 - 所以在函数中计算张量的偏导数,每次计算完修改完参数要清空梯度的计算。
不清空梯度计算:
x = torch.ones(4, requires_grad=True)
y = (2*x + 1).sum()
z = (2*x).sum()
y.backward()
print("第一次偏导:",x.grad)
z.backward()
print("第二次偏导:",x.grad)
会累加
使用张量.grad.zero_()
方法清空梯度的计算:
x = torch.ones(4, requires_grad=True)
y = (2*x + 1).sum()
z = (2*x).sum()
y.backward()
x.grad.zero_()
print("第一次偏导:",x.grad)
z.backward()
print("第二次偏导:",x.grad)