什么时候需要 pytorch 自定义函数(而不仅仅是一个模块)?

when is a pytorch custom function needed (rather than only a module)?

这里是 Pytorch 初学者!考虑以下自定义模块:

class Testme(nn.Module):
    def __init__(self):
        super(Testme, self).__init__()

def forward(self, x):
    return x / t_.max(x).expand_as(x)

据我对文档的理解: 我相信这也可以作为自定义 Function 实现。 Function 的子类需要 backward() 方法,但是 Module 没有。同样,在线性 Module 的文档示例中,它取决于线性 Function:

class Linear(nn.Module):
    def __init__(self, input_features, output_features, bias=True):
        ...    
    def forward(self, input):
        return Linear()(input, self.weight, self.bias)

问题:我不明白ModuleFunction之间的关系。在上面的第一个列表中(模块Testme),它应该有一个关联的功能吗?如果不是,那么可以通过子类化 Module 来实现这个 without a backward 方法,那么为什么 Function 总是需要 backward 方法?

也许 Functions 仅适用于不是由现有 torch 函数组成的函数?换句话说:如果模块的 forward 方法完全由先前定义的火炬函数组成,也许模块不需要关联的 Function

此信息是从官方 PyTorch 文档中收集和总结的。

torch.autograd.Function真正位于 PyTorch 中 autograd 包的核心。您在 PyTorch 中构建的任何图表以及您在 PyTorch 中对 Variables 进行的任何操作都基于 Function。任何函数都需要 __init__(), forward()backward() 方法(更多信息请见此处:http://pytorch.org/docs/notes/extending.html)。这使 PyTorch 能够计算结果并计算 Variables 的梯度。

nn.Module()相比之下,实际上只是为了方便组织你的模型,你的不同层等。例如,它将你模型中所有可训练的参数组织在.parameters()中,并允许你轻松地向模型添加另一层,等等。它是 而不是 定义向后方法的地方,因为在 forward() 方法中,您应该使用Function() 的子类,您已经为其定义了 backward()。因此,如果您在 forward() 中指定了操作顺序,PyTorch 已经知道如何反向传播梯度。

现在,你应该什么时候使用什么?

如果您的操作只是 PyTorch 中现有已实现函数的组合(如您上面的操作),那么您自己向 Function() 添加任何子类真的没有意义。因为您可以将操作堆叠起来并构建动态图。然而,将这些操作捆绑在一起是一个明智的想法。如果任何操作涉及可训练参数(例如神经网络的线性层),您应该将 nn.Module() 子类化并在 forward 方法中将您的操作捆绑在一起。这使您可以轻松访问参数(如上所述)以使用 torch.optim 等。如果您没有任何可训练的参数,我可能仍会将它们捆绑在一起,但是标准的 Python 函数,在那里你负责你使用的每个操作的实例化就足够了。

如果你有一个新的自定义操作(例如,一个带有一些复杂采样过程的新随机层),你应该继承 Function() 并定义 __init__(), forward()backward() 来告诉 PyTorch 如何使用此操作时计算结果以及如何计算梯度。之后,您应该创建一个功能版本来处理函数的实例化并使用您的操作,或者创建一个模块(如果您的操作具有可训练的参数)。同样,您可以在上面的 link 中阅读更多相关信息。