pytorch autograd计算标量函数二阶导数

计算标量函数: y = x 3 + s i n ( x ) y=x^3+sin(x) y=x3+sin(x)
x = 1 , π , 5 x=1,\pi,5 x=1,π,5时的一阶导 d y d x \frac{dy}{dx} dxdy和二阶导 d 2 y d x 2 \frac{d^2y}{dx^2} dx2d2y,程序代码如下:

# -*- coding: utf-8 -*-
"""
Created on Mon Sep 28 08:59:50 2020

@author: 周文青

利用torch.autograd计算单变量标量函数y=x^3+sin(x)在x分别为1,pi和5时的一阶导数和二
阶导数

"""
import torch as tc
import numpy as np

#%% 方法1:采用torch.autograd.grad
x  = tc.tensor([1, np.pi, 5],requires_grad=True)
y = x**3 +  tc.sin(x)
dy = 3*x**2 + tc.cos(x)
d2y = 6*x - tc.sin(x)

dydx = tc.autograd.grad(y, x, 
                        grad_outputs=tc.ones(x.shape), #注意这里需要人为指定
                        create_graph=True, 
                        retain_graph=True) # 为计算二阶导保持计算图
print(dydx) # 注意输出是一个tuple,取第一个元素
# (tensor([ 3.5403, 28.6088, 75.2837], grad_fn=),)
print(dy)
# tensor([ 3.5403, 28.6088, 75.2837], grad_fn=)

d2ydx2 = tc.autograd.grad(dydx[0],x, 
                          grad_outputs=tc.ones(x.shape), 
                          create_graph=False) # 默认会自动销毁计算图
print(d2ydx2)
# (tensor([ 5.1585, 18.8496, 30.9589]),)
print(d2y)
# tensor([ 5.1585, 18.8496, 30.9589], grad_fn=)

#%% 方法2:采用torch.autograd.backword
x  = tc.tensor([1, np.pi, 5],requires_grad=True)
y = x**3 +  tc.sin(x)
dy = 3*x**2 + tc.cos(x)
d2y = 6*x - tc.sin(x)

tc.autograd.backward(y, grad_tensors=tc.ones(x.shape),
           create_graph=True, retain_graph=False)
print(x.grad) #一阶导
# tensor([ 3.5403, 28.6088, 75.2837], grad_fn=)
tc.autograd.backward(x.grad, grad_tensors=tc.ones(x.shape),
           create_graph=False, retain_graph=False)

#采用backword的方法并且在求一阶导的时候设置了create_graph时,该结果是两次梯度的累加结果
print(x.grad) 
# tensor([  8.6988,  47.4584, 106.2426], grad_fn=)

pytorch实现了自动微分功能,可以自动计算梯度,因此后续可以研究使用pytorch实现一些利用梯度信息的优化算法,包括单变量情况和多变量情况的,例如one line search中的牛顿法梯度下降法共轭梯度算法等。

你可能感兴趣的:(深度学习,最优化,自动微分,pytorch,autograd)