跳至主要內容

3、自动微分机制、优化器

T4mako大约 2 分钟

3、自动微分机制、优化器

求梯度的两种方法

  • 通过反向传播 backward 方法实现梯度计算。

    该方法求得的梯度将存在对应 tenseor 的 grad 属性

  • 也可以调用 torch.autograd.grad 函数来实现求梯度计算

注意:使用上述方法求梯度后必须清零,否则(tensor.grad)会造成累加计算

  • optimizer.zero_grad()

创建需要求导的参数

  • x = torch.tensor(value,requires_grad=True)
    
  • x = torch.tensor(value)
    x.requires_grad = True
    

优化器

3.1、backward 方法求导数

  • backward标量 张量上调用,该方法求得的梯度将存在对应自变量张量的 grad 属性下。
  • backward非标量 张量上调用,则要传入一个和它 同形gradient 参数张量。

相当于用该 gradient 参数张量与调用张量作向量点乘,得到的标量结果再反向传播。

# backward  标量的反向传播
import numpy as np 
import torch 

# f(x) = a*x**2 + b*x + c 的导数
x = torch.tensor(0.0,requires_grad = True) # x 需要被求导
a = torch.tensor(1.0)
b = torch.tensor(-2.0)
c = torch.tensor(1.0)

y = a*torch.pow(x,2) + b*x + c 

y.backward()
dy_dx = x.grad # tensor(-2.)

# 非标量的反向传播
x = torch.tensor([[0.0,0.0],[1.0,2.0]],requires_grad = True) # x 需要被求导
y = a*torch.pow(x,2) + b*x + c 

gradient = torch.tensor([[1.0,1.0],[1.0,1.0]])
y.backward(gradient = gradient)
x_grad = x.grad # # tensor([[-2., -2.],[ 0.,  2.]])

3.2、利用 autograd.grad 方法求导数

import numpy as np 
import torch 

# f(x) = a*x**2 + b*x + c的导数

x = torch.tensor(0.0,requires_grad = True) # x 需要被求导
a = torch.tensor(1.0)
b = torch.tensor(-2.0)
c = torch.tensor(1.0)
y = a*torch.pow(x,2) + b*x + c

# create_graph 设置为 True 将允许创建更高阶的导数(对返回的变量二导,三导)
dy_dx = torch.autograd.grad(y,x,create_graph=True)[0]
print(dy_dx.data) # tensor(-2.)

# 求二阶导数
dy2_dx2 = torch.autograd.grad(dy_dx,x)[0] # tensor(2.)
import numpy as np 
import torch 

x1 = torch.tensor(1.0,requires_grad = True) # x 需要被求导
x2 = torch.tensor(2.0,requires_grad = True)

y1 = x1*x2
y2 = x1+x2

# 允许同时对多个自变量求导数
(dy1_dx1,dy1_dx2) = torch.autograd.grad(outputs=y1,inputs = [x1,x2],retain_graph = True)
print(dy1_dx1,dy1_dx2) # tensor(2.) tensor(1.)

# 如果有多个因变量,相当于把多个因变量的梯度结果求和
(dy12_dx1,dy12_dx2) = torch.autograd.grad(outputs=[y1,y2],inputs = [x1,x2])
print(dy12_dx1,dy12_dx2) # tensor(3.) tensor(2.)

3.3、利用自动微分和优化器求 optimizer 最小值

![image-20240730143417803](E:\Study=my repo\vuepress-hope-bloc\my-docs\src\code\python\Machine Learning\Pytorch\assets\image-20240730143417803.png)

import numpy as np 
import torch 

# f(x) = a*x**2 + b*x + c 的最小值

x = torch.tensor(0.0,requires_grad = True) # x需要被求导
a = torch.tensor(1.0)
b = torch.tensor(-2.0)
c = torch.tensor(1.0)

optimizer = torch.optim.SGD(params=[x],lr = 0.01)


def f(x):
    result = a*torch.pow(x,2) + b*x + c 
    return(result)

for i in range(500):
    optimizer.zero_grad() # 清零所有的梯度信息,不清零,x.grad 实现累加
    y = f(x)
    y.backward() # 反向传播,计算梯度
    optimizer.step() # 更新参数
   
print("y=",f(x).data,";","x=",x.data) # y= tensor(0.) ; x= tensor(1.0000)

评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v2.15.5