当前位置:   article > 正文

Pytorch自动微分机制_pytorch 自动微分

pytorch 自动微分

神经网络通常依赖反向传播求梯度来更新网络参数,求梯度过程通常是一件非常复杂而容易出错的事情。

深度学习框架可以帮助我们自动地完成这种求梯度运算。

Pytorch一般通过反向传播 backward 方法 实现这种求梯度计算。该方法求得的梯度将存在对应自变量张量的grad属性下。

除此之外,也能够调用torch.autograd.grad 函数来实现求梯度计算。

这就是Pytorch的自动微分机制。

一,利用backward方法求导数

backward 方法通常在一个标量张量上调用,该方法求得的梯度将存在对应自变量张量的grad属性下。

如果调用的张量非标量,则要传入一个和它同形状 的gradient参数张量。

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

1, 标量的反向传播

  1. import numpy as np
  2. import torch
  3. # f(x) = a*x**2 + b*x + c的导数
  4. x = torch.tensor(0.0,requires_grad = True) # x需要被求导
  5. a = torch.tensor(1.0)
  6. b = torch.tensor(-2.0)
  7. c = torch.tensor(1.0)
  8. y = a*torch.pow(x,2) + b*x + c
  9. y.backward()
  10. dy_dx = x.grad
  11. print(dy_dx)
tensor(-2.)

2, 非标量的反向传播

  1. import numpy as np
  2. import torch
  3. # f(x) = a*x**2 + b*x + c
  4. x = torch.tensor([[0.0,0.0],[1.0,2.0]],requires_grad = True) # x需要被求导
  5. a = torch.tensor(1.0)
  6. b = torch.tensor(-2.0)
  7. c = torch.tensor(1.0)
  8. y = a*torch.pow(x,2) + b*x + c
  9. gradient = torch.tensor([[1.0,1.0],[1.0,1.0]])
  10. print("x:\n",x)
  11. print("y:\n",y)
  12. y.backward(gradient = gradient)
  13. x_grad = x.grad
  14. print("x_grad:\n",x_grad)
  1. x:
  2. tensor([[0., 0.],
  3. [1., 2.]], requires_grad=True)
  4. y:
  5. tensor([[1., 1.],
  6. [0., 1.]], grad_fn=<AddBackward0>)
  7. x_grad:
  8. tensor([[-2., -2.],
  9. [ 0., 2.]])

3, 非标量的反向传播可以用标量的反向传播实现

  1. import numpy as np
  2. import torch
  3. # f(x) = a*x**2 + b*x + c
  4. x = torch.tensor([[0.0,0.0],[1.0,2.0]],requires_grad = True) # x需要被求导
  5. a = torch.tensor(1.0)
  6. b = torch.tensor(-2.0)
  7. c = torch.tensor(1.0)
  8. y = a*torch.pow(x,2) + b*x + c
  9. gradient = torch.tensor([[1.0,1.0],[1.0,1.0]])
  10. z = torch.sum(y*gradient)
  11. print("x:",x)
  12. print("y:",y)
  13. z.backward()
  14. x_grad = x.grad
  15. print("x_grad:\n",x_grad)
  1. x: tensor([[0., 0.],
  2. [1., 2.]], requires_grad=True)
  3. y: tensor([[1., 1.],
  4. [0., 1.]], grad_fn=<AddBackward0>)
  5. x_grad:
  6. tensor([[-2., -2.],
  7. [ 0., 2.]])

二,利用autograd.grad方法求导数

  1. import numpy as np
  2. import torch
  3. # f(x) = a*x**2 + b*x + c的导数
  4. x = torch.tensor(0.0,requires_grad = True) # x需要被求导
  5. a = torch.tensor(1.0)
  6. b = torch.tensor(-2.0)
  7. c = torch.tensor(1.0)
  8. y = a*torch.pow(x,2) + b*x + c
  9. # create_graph 设置为 True 将允许创建更高阶的导数
  10. dy_dx = torch.autograd.grad(y,x,create_graph=True)[0]
  11. print(dy_dx.data)
  12. # 求二阶导数
  13. dy2_dx2 = torch.autograd.grad(dy_dx,x)[0]
  14. print(dy2_dx2.data)
  1. tensor(-2.)
  2. tensor(2.)
  1. import numpy as np
  2. import torch
  3. x1 = torch.tensor(1.0,requires_grad = True) # x需要被求导
  4. x2 = torch.tensor(2.0,requires_grad = True)
  5. y1 = x1*x2
  6. y2 = x1+x2
  7. # 允许同时对多个自变量求导数
  8. (dy1_dx1,dy1_dx2) = torch.autograd.grad(outputs=y1,inputs = [x1,x2],retain_graph = True)
  9. print(dy1_dx1,dy1_dx2)
  10. # 如果有多个因变量,相当于把多个因变量的梯度结果求和
  11. (dy12_dx1,dy12_dx2) = torch.autograd.grad(outputs=[y1,y2],inputs = [x1,x2])
  12. print(dy12_dx1,dy12_dx2)
  1. tensor(2.) tensor(1.)
  2. tensor(3.) tensor(2.)

三,利用自动微分和优化器求最小值

  1. import numpy as np
  2. import torch
  3. # f(x) = a*x**2 + b*x + c的最小值
  4. x = torch.tensor(0.0,requires_grad = True) # x需要被求导
  5. a = torch.tensor(1.0)
  6. b = torch.tensor(-2.0)
  7. c = torch.tensor(1.0)
  8. optimizer = torch.optim.SGD(params=[x],lr = 0.01)
  9. def f(x):
  10. result = a*torch.pow(x,2) + b*x + c
  11. return(result)
  12. for i in range(500):
  13. optimizer.zero_grad()
  14. y = f(x)
  15. y.backward()
  16. optimizer.step()
  17. print("y=",f(x).data,";","x=",x.data)
y= tensor(0.) ; x= tensor(1.0000)
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/288290
推荐阅读
相关标签
  

闽ICP备14008679号