- torch.autograd在写求导代码时,参与计算的非torch.Tensor类型的数值返回梯度只能为None,并且不可训练参数的梯度可以不为None,但是反向传播后查询其梯度时只有None与之对应,也就是说网络中的一些参数原先可训练但是后来令其不训练之后,可以不改变自己定义的求导函数(backward)中不可训练的参数返回值为None
下面给出例子,其中x为不可求导参数,a为非torch.Tensor的参数
其中:
- x可以返回梯度,但是在
i.backward()
之后,x的梯度查询为None, - a对应的梯度只能为
None
,如果修改之后会出现以下报错:
Traceback (most recent call last):
File “test.py”, line 41, in
i.backward()
File “/home/skt1faker/anaconda3/lib/python3.8/site-packages/torch/_tensor.py”, line 255, in backward
torch.autograd.backward(self, gradient, retain_graph, create_graph, inputs=inputs)
File “/home/skt1faker/anaconda3/lib/python3.8/site-packages/torch/autograd/init.py”, line 147, in backward
Variable._execution_engine.run_backward(
RuntimeError: function funcBackward returned a gradient different than None at position 4, but the corresponding forward input was not a Variable
大概意思就是参数a不是Variable数据类型的数据!
import torch
from torch.autograd import Function as Function
import math
class func(Function): # 这是一个多元函数,拥有混合计算
def __init__(self):
Function.__init__(self)
self.a = 100
@staticmethod
def forward(ctx,x,y,z,const): # const*xye^z
ctx.save_for_backward(x,y,torch.tensor(math.exp(z)),torch.tensor(const)) # 注意这里只能存储torch.Tensor
# ctx.save_for_backward(x,y,math.exp(z),torch.tensor(const)) # 注意这里math.exp返回值为float,这里会报错为有变量不是torch.tensor
"""
ctx.save_for_backward(x)
ctx.save_for_backward(y)
ctx.save_for_backward(math.exp(z))
ctx.save_for_backward(torch.tensor(const))
""" # 注意ctx中的变量只能一次性储存完,如果这样存储的话 只能存储最后一个torch.tensor(const)
return x*y*math.exp(z)*const
@staticmethod
def backward(ctx, output_grad):
x,y,ez,const = ctx.saved_tensors # 后面必须为","
x_grad = y*ez*const
y_grad = x*ez*const
z_grad = x*y*ez*const
return x_grad*output_grad, y_grad*output_grad, z_grad*output_grad,None # 常数没有导数,设为None
x = torch.tensor(10.)
y = torch.tensor(2., requires_grad = True)
z = torch.tensor(5., requires_grad = True)
a = 10
h = func.apply(x,y,z,a) #
i = 10 * h
i.backward()