Pytorch中如何调用forward()函数

目录
  • Pytorch调用forward()函数
  • Pytorch函数调用的问题和源码解读
  • 总结

Pytorch调用forward()函数

Module类是nn模块里提供的一个模型构造类,是所有神经网络模块的基类,我们可以继承它来定义我们想要的模型。

下面继承Module类构造本节开头提到的多层感知机。

这里定义的MLP类重载了Module类的__init__函数和forward函数。

它们分别用于创建模型参数和定义前向计算。

前向计算也即正向传播。

import torch
from torch import nn
 
class MLP(nn.Module):
    # 声明带有模型参数的层,这里声明了两个全连接层
    def __init__(self, **kwargs):
        # 调用MLP父类Module的构造函数来进行必要的初始化。这样在构造实例时还可以指定其他函数
        # 参数,如“模型参数的访问、初始化和共享”一节将介绍的模型参数params
        super(MLP, self).__init__(**kwargs)
        self.hidden = nn.Linear(784, 256) # 隐藏层
        self.act = nn.ReLU()
        self.output = nn.Linear(256, 10)  # 输出层
 
 
    # 定义模型的前向计算,即如何根据输入x计算返回所需要的模型输出
    def forward(self, x):
        a = self.act(self.hidden(x))
        return self.output(a)
  
X = torch.rand(2, 784)
net = MLP()
print(net)
net(X)

输出:

MLP( (hidden): Linear(in_features=784, out_features=256, bias=True) (act): ReLU() (output): Linear(in_features=256, out_features=10, bias=True) ) tensor([[-0.1798, -0.2253, 0.0206, -0.1067, -0.0889, 0.1818, -0.1474, 0.1845, -0.1870, 0.1970], [-0.1843, -0.1562, -0.0090, 0.0351, -0.1538, 0.0992, -0.0883, 0.0911, -0.2293, 0.2360]], grad_fn=<ThAddmmBackward>)

为什么会调用forward()呢,是因为Module中定义了__call__()函数,该函数调用了forward()函数,当执行net(x)的时候,会自动调用__call__()函数

Pytorch函数调用的问题和源码解读

最近用到 softmax 函数,但是发现 softmax 的写法五花八门,记录如下

# torch._C._VariableFunctions
torch.softmax(x, dim=-1)
# class
softmax = torch.nn.Softmax(dim=-1)
x=softmax(x)
# function
x = torch.nn.functional.softmax(x, dim=-1)

简单测试了一下,用 torch.nn.Softmax 类是最慢的,另外两个差不多

torch.nn.Softmax 源码如下,可以看到这是个类,而他这里的 return F.softmax(input, self.dim, _stacklevel=5) 调用的是 torch.nn.functional.softmax

class Softmax(Module):
    r"""Applies the Softmax function to an n-dimensional input Tensor
    rescaling them so that the elements of the n-dimensional output Tensor
    lie in the range [0,1] and sum to 1.

    Softmax is defined as:

    .. math::
        \text{Softmax}(x_{i}) = \frac{\exp(x_i)}{\sum_j \exp(x_j)}

    When the input Tensor is a sparse tensor then the unspecifed
    values are treated as ``-inf``.

    Shape:
        - Input: :math:`(*)` where `*` means, any number of additional
          dimensions
        - Output: :math:`(*)`, same shape as the input

    Returns:
        a Tensor of the same dimension and shape as the input with
        values in the range [0, 1]

    Args:
        dim (int): A dimension along which Softmax will be computed (so every slice
            along dim will sum to 1).

    .. note::
        This module doesn't work directly with NLLLoss,
        which expects the Log to be computed between the Softmax and itself.
        Use `LogSoftmax` instead (it's faster and has better numerical properties).

    Examples::

        >>> m = nn.Softmax(dim=1)
        >>> input = torch.randn(2, 3)
        >>> output = m(input)

    """
    __constants__ = ['dim']
    dim: Optional[int]

    def __init__(self, dim: Optional[int] = None) -> None:
        super(Softmax, self).__init__()
        self.dim = dim

    def __setstate__(self, state):
        self.__dict__.update(state)
        if not hasattr(self, 'dim'):
            self.dim = None

    def forward(self, input: Tensor) -> Tensor:
        return F.softmax(input, self.dim, _stacklevel=5)

    def extra_repr(self) -> str:
        return 'dim={dim}'.format(dim=self.dim)

torch.nn.functional.softmax 函数源码如下,可以看到 ret = input.softmax(dim) 实际上调用了 torch._C._VariableFunctions 中的 softmax 函数

def softmax(input: Tensor, dim: Optional[int] = None, _stacklevel: int = 3, dtype: Optional[DType] = None) -> Tensor:
    r"""Applies a softmax function.

    Softmax is defined as:

    :math:`\text{Softmax}(x_{i}) = \frac{\exp(x_i)}{\sum_j \exp(x_j)}`

    It is applied to all slices along dim, and will re-scale them so that the elements
    lie in the range `[0, 1]` and sum to 1.

    See :class:`~torch.nn.Softmax` for more details.

    Args:
        input (Tensor): input
        dim (int): A dimension along which softmax will be computed.
        dtype (:class:`torch.dtype`, optional): the desired data type of returned tensor.
          If specified, the input tensor is casted to :attr:`dtype` before the operation
          is performed. This is useful for preventing data type overflows. Default: None.

    .. note::
        This function doesn't work directly with NLLLoss,
        which expects the Log to be computed between the Softmax and itself.
        Use log_softmax instead (it's faster and has better numerical properties).

    """
    if has_torch_function_unary(input):
        return handle_torch_function(softmax, (input,), input, dim=dim, _stacklevel=_stacklevel, dtype=dtype)
    if dim is None:
        dim = _get_softmax_dim("softmax", input.dim(), _stacklevel)
    if dtype is None:
        ret = input.softmax(dim)
    else:
        ret = input.softmax(dim, dtype=dtype)
    return ret

那么不如直接调用 built-in C 的函数?

但是有个博客 A selective excursion into the internals of PyTorch 里说

Note: That bilinear is exported as torch.bilinear is somewhat accidental. Do use the documented interfaces, here torch.nn.functional.bilinear whenever you can!

意思是说 built-in C 能被 torch.xxx 直接调用是意外的,强烈建议使用 torch.nn.functional.xxx 这样的接口

看到最新的 transformer 官方代码里也用的是 torch.nn.functional.softmax,还是和他们一致更好(虽然他们之前用的是类。。。)

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • pytorch __init__、forward与__call__的用法小结

    1.介绍 当我们使用pytorch来构建网络框架的时候,也会遇到和tensorflow(tensorflow __init__.build 和call小结)类似的情况,即经常会遇到__init__.forward和call这三个互相搭配着使用,那么它们的主要区别又在哪里呢? 1)__init__主要用来做参数初始化用,比如我们要初始化卷积的一些参数,就可以放到这里面,这点和tf里面的用法是一样的 2)forward是表示一个前向传播,构建网络层的先后运算步骤 3)__call__的功能其实和fo

  • pytorch 中forward 的用法与解释说明

    前言 最近在使用pytorch的时候,模型训练时,不需要使用forward,只要在实例化一个对象中传入对应的参数就可以自动调用 forward 函数 即: forward 的使用 class Module(nn.Module): def __init__(self): super(Module, self).__init__() # ...... def forward(self, x): # ...... return x data = ..... #输入数据 # 实例化一个对象 module

  • pytorch hook 钩子函数的用法

    钩子编程(hooking),也称作“挂钩”,是计算机程序设计术语,指通过拦截软件模块间的函数调用.消息传递.事件传递来修改或扩展操作系统.应用程序或其他软件组件的行为的各种技术.处理被拦截的函数调用.事件.消息的代码,被称为钩子(hook). Hook 是 PyTorch 中一个十分有用的特性.利用它,我们可以不必改变网络输入输出的结构,方便地获取.改变网络中间层变量的值和梯度.这个功能被广泛用于可视化神经网络中间层的 feature.gradient,从而诊断神经网络中可能出现的问题,分析网络

  • Pytorch中如何调用forward()函数

    目录 Pytorch调用forward()函数 Pytorch函数调用的问题和源码解读 总结 Pytorch调用forward()函数 Module类是nn模块里提供的一个模型构造类,是所有神经网络模块的基类,我们可以继承它来定义我们想要的模型. 下面继承Module类构造本节开头提到的多层感知机. 这里定义的MLP类重载了Module类的__init__函数和forward函数. 它们分别用于创建模型参数和定义前向计算. 前向计算也即正向传播. import torch from torch

  • 浅谈Pytorch中的torch.gather函数的含义

    pytorch中的gather函数 pytorch比tensorflow更加编程友好,所以准备用pytorch试着做最近要做的一些实验. 立个flag开始学习pytorch,新开一个分类整理学习pytorch中的一些踩到的泥坑. 今天刚开始接触,读了一下documentation,写一个一开始每太搞懂的函数gather b = torch.Tensor([[1,2,3],[4,5,6]]) print b index_1 = torch.LongTensor([[0,1],[2,0]]) ind

  • 详解pytorch中squeeze()和unsqueeze()函数介绍

    squeeze的用法主要就是对数据的维度进行压缩或者解压. 先看torch.squeeze() 这个函数主要对数据的维度进行压缩,去掉维数为1的的维度,比如是一行或者一列这种,一个一行三列(1,3)的数去掉第一个维数为一的维度之后就变成(3)行.squeeze(a)就是将a中所有为1的维度删掉.不为1的维度没有影响.a.squeeze(N) 就是去掉a中指定的维数为一的维度.还有一种形式就是b=torch.squeeze(a,N) a中去掉指定的定的维数为一的维度. 再看torch.unsque

  • 解析Pytorch中的torch.gather()函数

    参数说明 以官方说明为例,gather()函数需要三个参数,输入input,维度dim,以及索引index input必须为Tensor类型 dim为int类型,代表从哪个维度进行索引 index为LongTensor类型 举例说明 input=torch.tensor([[1,2,3],[4,5,6]]) #作为输入 index1=torch.tensor([[0,1,1],[0,1,1]]) #作为索引矩阵 # dim=0时,按列进行索引 print (torch.gather(input,

  • python中子类调用父类函数的方法示例

    前言 本文主要给大家介绍了关于python子类调用父类函数的相关内容,Python中子类中的__init__()函数会覆盖父类的函数,一些情况往往需要在子类里调用父类函数.下面话不多说了,来一起看看详细的介绍: 如下例程里,???处是需要调用父类函数的地方,接下来结合例程具体介绍. # -*- coding:utf-8 -*- class Student: def __init__(self,name): self.name=name def ps(self): print('I am %s'%

  • 解析php中如何调用用户自定义函数

    先放上来别人的例子吧:call_user_func函数类似于一种特别的调用函数的方法,使用方法如下:    复制代码 代码如下: function a($b,$c)    {    echo $b;    echo $c;    }    call_user_func('a', "111","222");    call_user_func('a', "333","444");    //显示 111 222 333 444 

  • pytorch 中autograd.grad()函数的用法说明

    我们在用神经网络求解PDE时, 经常要用到输出值对输入变量(不是Weights和Biases)求导: 在训练WGAN-GP 时, 也会用到网络对输入变量的求导. 以上两种需求, 均可以用pytorch 中的autograd.grad() 函数实现. autograd.grad(outputs, inputs, grad_outputs=None, retain_graph=None, create_graph=False, only_inputs=True, allow_unused=False

  • Pytorch中的backward()多个loss函数用法

    Pytorch的backward()函数 假若有多个loss函数,如何进行反向传播和更新呢? x = torch.tensor(2.0, requires_grad=True) y = x**2 z = x # 反向传播 y.backward() x.grad tensor(4.) z.backward() x.grad tensor(5.) ## 累加 补充:Pytorch中torch.autograd ---backward函数的使用方法详细解析,具体例子分析 backward函数 官方定义

  • C语言中调用Lua函数实例

    记得上学时,初中英文课本中,上网叫做surfing the internet,中文叫网上冲浪.那个时期,人们经常称互联网为赛博空间.如今工作了,大量的零碎时间用于上微博,知乎,QQ,这些碎片化的阅读让人读起来轻松,也能获取些粗浅的信息.然而它们是消耗时间的黑洞,时间就这样一分一秒地飞逝,年末的时候,知乎会告诉你回答了多少问题,阅读了相当于一部<红楼梦>那么多的文字.只是当你静下来一想,这些浅阅读并没给你带来有深度,系统的知识.在你的时间线上,两条相邻信息往往是八竿子也打不着的.而且你还时不时去

随机推荐