我正在学习PyTorch教程,定义新的自动求导函数。我想要实现的自动求导函数是torch.nn.functional.max_pool1d
的一个包装器。以下是我的代码:
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.autograd as tag
class SquareAndMaxPool1d(tag.Function):
@staticmethod
def forward(ctx, input, kernel_size, stride=None, padding=0, dilation=1, \
return_indices=False, ceil_mode=False):
ctx.save_for_backward( input )
inputC = input.clone() #copy input
inputC *= inputC
output = F.max_pool1d(inputC, kernel_size, stride=stride, \
padding=padding, dilation=dilation, \
return_indices=return_indices, \
ceil_mode=ceil_mode)
return output
@staticmethod
def backward(ctx, grad_output):
input, = ctx.saved_tensors
grad_input = get_max_pool1d_grad_somehow(grad_output)
return 2.0*input*grad_input
我的问题是:如何得到包装函数的梯度?我知道可能有其他方法可以做到这一点,因为我提出的示例非常简单,但我想要做的适合这个框架,并且需要我实现一个
autograd
函数。编辑:在查看此博客文章后,我决定尝试以下
backward
:def backward(ctx, grad_output):
input, output = ctx.saved_tensors
grad_input = output.backward(grad_output)
return 2.0*input*grad_input
将output
加入保存的变量中。然后我运行以下代码:
x = np.random.randn(1,1,5)
xT = torch.from_numpy(x)
xT.requires_grad=True
f = SquareAndMaxPool1d.apply
s = torch.sum(f(xT,2))
s.backward()
我得到了总线错误:10
。
假设xT
是tensor([[[ 1.69533562, -0.21779421, 2.28693953, -0.86688095, -1.01033497]]], dtype=torch.float64)
,那么我期望在调用s.backward()
后找到xT.grad
为tensor([[[ 3.39067124, -0. , 9.14775812, -0. , -2.02066994]]], dtype=torch.float64)
(即2*x*grad_of_max_pool
,其中grad_of_max_pool
包含tensor([[[1., 0., 2., 0., 1.]]], dtype=torch.float64)
)。
backward
在grad_input = output.backward(grad_output)
处发生递归调用。所以我需要找到其他方法来获取max_pool1d
的梯度。我知道如何在纯Python中实现这个,但结果会比包装库代码慢得多。