1、Autograd 求导机制

    我们在用神经网络求解PDE时, 经常要用到输出值对输入变量(不是Weights和Biases)求导; 例如在训练WGAN-GP 时, 也会用到网络对输入变量的求导,pytorch中通过 Autograd 方法进行求导,其求导规则如下:

1.1当x为向量,y为一标量时

     

adam pytorch 用法 pytorch add_标量

      adam pytorch 用法 pytorch add_adam pytorch 用法_02

通过autograd 计算的梯度为:

                                      

adam pytorch 用法 pytorch add_元组_03

1.2先假设x,y为一维向量

             

adam pytorch 用法 pytorch add_元组_04

                    

adam pytorch 用法 pytorch add_pytorch_05

      

其对应的jacobi(雅可比)矩阵为

                 

adam pytorch 用法 pytorch add_深度学习_06

grad_outputs 是一个与因变量 y 的shape 一致的向量

                       

adam pytorch 用法 pytorch add_adam pytorch 用法_07

在给定grad_outputs 后,通过Autograd 方法 计算的梯度如下:

           

adam pytorch 用法 pytorch add_标量_08

      

 

1.3 当 x 为1维向量,Y为2维向量

                  

adam pytorch 用法 pytorch add_深度学习_09

给出grad_outputs  与Y的shape一致                 

                            

adam pytorch 用法 pytorch add_pytorch_10

Y 与x的jacobi矩阵

                                   

adam pytorch 用法 pytorch add_pytorch_11

                        

adam pytorch 用法 pytorch add_adam pytorch 用法_12


则 Y 对 x 的梯度:        

                                          

adam pytorch 用法 pytorch add_深度学习_13

1.4 当 X ,Y均为2维向量时

                                    

adam pytorch 用法 pytorch add_adam pytorch 用法_14

     

adam pytorch 用法 pytorch add_标量_15

                

adam pytorch 用法 pytorch add_元组_16

1.5 当X  Y为更高维度时,可以按照上述办法转化为低维度的求导

值得注意的是:

  • 求导后的梯度shape总与自变量X保持一致
  • 对自变量求导的顺序并不会影响结果,某自变量的梯度值会放到该自变量原来相同位置
  • 梯度是由每个自变量的导数值组成的向量,既有大小又有方向
  • grad_outputs 与 因变量Y的shape一致,每一个参数相当于对因变量中相同位置的y进行一个加权。

2 pytorch求导方法

2.1 在求导前需要对需要求导的自变量进行声明

adam pytorch 用法 pytorch add_标量_17

adam pytorch 用法 pytorch add_pytorch_18

2.2 torch.autograd.gard()

grad =  autograd.grad( outputs, inputs, grad_outputs=None, retain_graph=None,    create_graph=False, only_inputs=True, allow_unused=False )

参数解释:

outputs:求导的因变量 Y

inputs : 求导自变量 X

grad_outputs:

  • 当outputs为标量时,grad_outputs=None , 不需要写,
  • 当outputs 为向量,需要为其声明一个与outputs相同shape的参数矩阵,该矩阵中的每个参数的作用是,对outputs中相同位置的y进行一个加权。 不然会报错

adam pytorch 用法 pytorch add_元组_19

adam pytorch 用法 pytorch add_元组_20

adam pytorch 用法 pytorch add_adam pytorch 用法_21

  •     autograd.grad()返回的是元组数据类型,元组的长度与inputs长度相同,元组中每个单位的shape与相同位置的inputs相同

adam pytorch 用法 pytorch add_adam pytorch 用法_22

adam pytorch 用法 pytorch add_深度学习_23

retain_graph:

        1、当求完一次梯度后默认会把图信息释放掉,都会free掉计算图中所有缓存的buffers,当要连续进行几次求导时,可能会因为前面buffers不存在而报错。

adam pytorch 用法 pytorch add_元组_24

adam pytorch 用法 pytorch add_pytorch_25

因为第二个梯度计算z对x的导数,需要y对x的计算导数的缓存信息,但是在计算grad1后,保存信息被释放,找不到了,因此报错。

修改如下:

adam pytorch 用法 pytorch add_标量_26

adam pytorch 用法 pytorch add_标量_27

        2、一般计算的最后一个梯度可以不需要保存计算图信息,这样在计算后可以及时释放掉占用的内存。

        3、在pytorch中连续多次调用backward()也会出现这样的问题,对中间的backwad(),需要保持计算图信息

adam pytorch 用法 pytorch add_深度学习_28

create_graph: 若要计算高阶导数,则必须选为True

求二阶导方法如下:

adam pytorch 用法 pytorch add_adam pytorch 用法_29

adam pytorch 用法 pytorch add_标量_30

allow_unused: 允许输入变量不进入计算

2.3 torch.backward()

def backward(

                        gradient: Optional[Tensor] = None,

                        retain_graph: Any = None,

                        create_graph: Any = False,

                        inputs: Any = None) -> Any

                                                )

  • 如果需要计算导数,可以在tensor上直接调用.backward(),会返回该tensor所有自变量的导数。通过name(自变量名).grad 可以获得该自变量的梯度
  • 如果tensor是标量,则backward()不需要指定任何参数
  • 如果tensor是向量,则backward()需要指定gradient一个与tensorshape相同的参数矩阵,即这里的gradient 同 grad_outputs 作用和形式完全一样。

adam pytorch 用法 pytorch add_元组_31

adam pytorch 用法 pytorch add_pytorch_32