pytorch中forwod函数在父类中的调用方式解读

作者:Ai_Taoism 时间:2023-04-27 11:12:25 

pytorch forwod函数在父类中的调用

问题背景

最近在研究Detetron2的代码结构时,发现有些网络代码里面没有forward函数,却照样可以推理,深入挖掘之后,发现其将forword函数都写在了同一个父类里面。

这就牵涉到了下面这个问题,子类中没有forward函数,只有父类中有forward函数,这样能不能正常调用网络。

import torch.nn as nn

class Network1(nn.Module):
    def __init__(self):
        super().__init__()

    def forward(self,x):
        return x

class Network2(Network1):
    def __init__(self):
        super().__init__()

data = [1,2,3]
model = Network2().eval()
output = model(data)
print(output)

输出结果如下:

[1,2,3]

pytorch forward方法调用原理

在使用Pytorch自定义网络模型的时候,我们需要继承nn.Module这个类,然后定义forward方法来实现前向转播。

如下图的一个自定义的网络模型

pytorch中forwod函数在父类中的调用方式解读

首先该网络模型的初始化方法__init__需要继承父类nn.Module的初始化方法,用语句super().init()实现。

并在初始化方法里面,定义了卷积、BN、激活函数等。接下来定义forward方法,将整个网络连接起来。

有了上面的定义,我们可以实例化一个对象,例如:

fire2 = Fire(96, 128,16,64,64)

实现前向传播,使用 y= fire2(x) 其中x是该网络的输入,y是输出,实现了forward方法的额功能。

这里就会有人感到奇怪,forward作为Fire这个类的方法,使用的时候不应该是 y= fire2.forward(x)吗。

这里为什么一个类的实例可以当做方法直接使用?这是因为这个Fire类继承的父类nn.Module里面定义了__call__方法。

一个类如果定义了__call__方法,则该类的实例就可以作为一个方法那样直接使用。

例如下列代码[1]

class A():
   def __call__(self):
       print('i can be called like a function')

a = A()
a()

就会执行print函数,打印其中搞的文字。这里需要区别的是,实例化的时候,类的名称后面括号可以传递参数,例如前面实例化Fire的时候,传递in_channel,out_channel等参数。

但是要利用__call__的特性,是在实例名后面的括号中传递参数,例如上面的例子a(),这里虽然没有参数,但是也可以改变__call__的定义使之可以传递参数。

回到网络模型的内容上来。翻看nn.Module的部分源码[2],可以发现,nn.Module里面果然定义了__call__,并且传递了参数*input。在__call__的定义中国,调用了self.forward。

pytorch中forwod函数在父类中的调用方式解读

这里其实还有一个点值得注意。其实nn.Module里面并没有定义forward,但他却调用self.forward,严格来说,他是“想要”调用self.forward。

如果我们没有定义一个类,例如Fire,来继承nn.Module,并且在这个类里面定义forward,那么nn.Module中__call__下面的self.forward就是无效的。

这意味着,父类中__call__下面调用的函数,可以在继承他的子类中定义

下面给出一个简单的例子。

class father():
   def __call__(self):
       self.forward()
       print('I''m the father!')

class child(father):
   def forward(self):
       print('Forward!')
F=father()
C=child()

这里定义了父类father,并定义了继承他的一个子类child。此外还进行了他们的实例化。

显然,在father的__call__方法下面,调用了self.forward,但是没有定义。child在继承了father之后,定义了forward。

首先,这段代码不会报错,即使father的__call__下面的self.forward并没有定义,这也是前面我说的,虽然没有定义forward,但是可以理解为他“想要”调用self.forward。

那么在child记成了father之后,进行了forward的定义,这使得child本身可以调用forward。

在上面这段代码的基础上,如果我们执行F(),汇报下面这一段错误,这解释了forward没有定义,只是“想要”调用self.forward。

pytorch中forwod函数在父类中的调用方式解读

如果我们执行C(),则如下图输出。

显然,在child中补充了forward的定义,就可以成功调用。

pytorch中forwod函数在父类中的调用方式解读

来源:https://blog.csdn.net/ahhhhhh520/article/details/124437247

标签:pytorch,forwod,父类
0
投稿

猜你喜欢

  • Tensorflow实现神经网络拟合线性回归

    2022-10-09 06:24:49
  • python使用参数对嵌套字典进行取值的方法

    2022-04-12 10:13:27
  • MySQL8数据库安装及SQL语句详解

    2024-01-17 21:25:33
  • python可视化大屏库big_screen示例详解

    2021-10-16 14:32:39
  • 深入了解如何基于Python读写Kafka

    2021-02-13 09:33:09
  • sklearn-SVC实现与类参数详解

    2023-09-04 18:10:43
  • pandas中DataFrame重置索引的几种方法

    2023-06-10 00:26:45
  • DNS优化的原理和方法

    2012-04-26 16:43:56
  • Python如何生成随机数及random随机数模块应用

    2022-07-28 22:24:21
  • python选择排序算法实例总结

    2023-08-29 06:58:28
  • python远程登录代码

    2022-09-12 15:48:15
  • git本地分支和stash内容报错消失的问题

    2023-10-19 01:48:47
  • python-sys.stdout作为默认函数参数的实现

    2022-11-23 02:50:35
  • vue实现鼠标滑动展示tab栏切换

    2023-07-02 16:38:05
  • 一小时学会TensorFlow2之大幅提高模型准确率

    2021-07-25 16:25:20
  • keras实现VGG16 CIFAR10数据集方式

    2023-08-19 08:27:08
  • Mysql服务添加 iptables防火墙策略的方案

    2024-01-21 14:44:34
  • python 爬取京东指定商品评论并进行情感分析

    2021-03-02 19:56:53
  • Python 中创建 PostgreSQL 数据库连接池

    2024-01-19 22:33:37
  • VueJs单页应用实现微信网页授权及微信分享功能示例

    2024-04-16 09:35:50
  • asp之家 网络编程 m.aspxhome.com