網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
pytorch forwod函數(shù)在父類(lèi)中的調(diào)用
問(wèn)題背景
最近在研究Detetron2的代碼結(jié)構(gòu)時(shí),發(fā)現(xiàn)有些網(wǎng)絡(luò)代碼里面沒(méi)有forward函數(shù),卻照樣可以推理,深入挖掘之后,發(fā)現(xiàn)其將forword函數(shù)都寫(xiě)在了同一個(gè)父類(lèi)里面。
這就牽涉到了下面這個(gè)問(wèn)題,子類(lèi)中沒(méi)有forward函數(shù),只有父類(lèi)中有forward函數(shù),這樣能不能正常調(diào)用網(wǎng)絡(luò)。
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)
輸出結(jié)果如下:
[1,2,3]
pytorch forward方法調(diào)用原理
在使用Pytorch自定義網(wǎng)絡(luò)模型的時(shí)候,我們需要繼承nn.Module這個(gè)類(lèi),然后定義forward方法來(lái)實(shí)現(xiàn)前向轉(zhuǎn)播。
如下圖的一個(gè)自定義的網(wǎng)絡(luò)模型
首先該網(wǎng)絡(luò)模型的初始化方法__init__需要繼承父類(lèi)nn.Module的初始化方法,用語(yǔ)句super().init()實(shí)現(xiàn)。
并在初始化方法里面,定義了卷積、BN、激活函數(shù)等。接下來(lái)定義forward方法,將整個(gè)網(wǎng)絡(luò)連接起來(lái)。
有了上面的定義,我們可以實(shí)例化一個(gè)對(duì)象,例如:
fire2 = Fire(96, 128,16,64,64)
實(shí)現(xiàn)前向傳播,使用?y= fire2(x)?其中x是該網(wǎng)絡(luò)的輸入,y是輸出,實(shí)現(xiàn)了forward方法的額功能。
這里就會(huì)有人感到奇怪,forward作為Fire這個(gè)類(lèi)的方法,使用的時(shí)候不應(yīng)該是?y= fire2.forward(x)嗎。
這里為什么一個(gè)類(lèi)的實(shí)例可以當(dāng)做方法直接使用?這是因?yàn)檫@個(gè)Fire類(lèi)繼承的父類(lèi)nn.Module里面定義了__call__方法。
一個(gè)類(lèi)如果定義了__call__方法,則該類(lèi)的實(shí)例就可以作為一個(gè)方法那樣直接使用。
例如下列代碼[1]
class A():
def __call__(self):
print('i can be called like a function')
a = A()
a()
就會(huì)執(zhí)行print函數(shù),打印其中搞的文字。這里需要區(qū)別的是,實(shí)例化的時(shí)候,類(lèi)的名稱后面括號(hào)可以傳遞參數(shù),例如前面實(shí)例化Fire的時(shí)候,傳遞in_channel,out_channel等參數(shù)。
但是要利用__call__的特性,是在實(shí)例名后面的括號(hào)中傳遞參數(shù),例如上面的例子a(),這里雖然沒(méi)有參數(shù),但是也可以改變__call__的定義使之可以傳遞參數(shù)。
回到網(wǎng)絡(luò)模型的內(nèi)容上來(lái)。翻看nn.Module的部分源碼[2],可以發(fā)現(xiàn),nn.Module里面果然定義了__call__,并且傳遞了參數(shù)*input。在__call__的定義中國(guó),調(diào)用了self.forward。
這里其實(shí)還有一個(gè)點(diǎn)值得注意。其實(shí)nn.Module里面并沒(méi)有定義forward,但他卻調(diào)用self.forward,嚴(yán)格來(lái)說(shuō),他是“想要”調(diào)用self.forward。
如果我們沒(méi)有定義一個(gè)類(lèi),例如Fire,來(lái)繼承nn.Module,并且在這個(gè)類(lèi)里面定義forward,那么nn.Module中__call__下面的self.forward就是無(wú)效的。
這意味著,父類(lèi)中__call__下面調(diào)用的函數(shù),可以在繼承他的子類(lèi)中定義。
下面給出一個(gè)簡(jiǎn)單的例子。
class father():
def __call__(self):
self.forward()
print('I''m the father!')
class child(father):
def forward(self):
print('Forward!')
F=father()
C=child()
這里定義了父類(lèi)father,并定義了繼承他的一個(gè)子類(lèi)child。此外還進(jìn)行了他們的實(shí)例化。
顯然,在father的__call__方法下面,調(diào)用了self.forward,但是沒(méi)有定義。child在繼承了father之后,定義了forward。
首先,這段代碼不會(huì)報(bào)錯(cuò),即使father的__call__下面的self.forward并沒(méi)有定義,這也是前面我說(shuō)的,雖然沒(méi)有定義forward,但是可以理解為他“想要”調(diào)用self.forward。
那么在child記成了father之后,進(jìn)行了forward的定義,這使得child本身可以調(diào)用forward。
在上面這段代碼的基礎(chǔ)上,如果我們執(zhí)行F(),匯報(bào)下面這一段錯(cuò)誤,這解釋了forward沒(méi)有定義,只是“想要”調(diào)用self.forward。
如果我們執(zhí)行C(),則如下圖輸出。
顯然,在child中補(bǔ)充了forward的定義,就可以成功調(diào)用。
總結(jié)
原文鏈接:https://blog.csdn.net/ahhhhhh520/article/details/124437247
相關(guān)推薦
- 2022-06-09 ASP.NET?Core使用EF創(chuàng)建關(guān)系模型_實(shí)用技巧
- 2022-11-03 PyCharm利用pydevd-pycharm實(shí)現(xiàn)Python遠(yuǎn)程調(diào)試的詳細(xì)過(guò)程_python
- 2022-08-13 Kafka復(fù)習(xí)計(jì)劃 - Kafka基礎(chǔ)知識(shí)以及集群參方案和參數(shù)
- 2022-04-11 MVVMLight項(xiàng)目之雙向數(shù)據(jù)綁定_Android
- 2022-05-20 springCloud_Feign遠(yuǎn)程調(diào)用
- 2022-05-12 正則判斷只能輸入大于0的正整數(shù)
- 2022-04-08 Android接入阿里云熱修復(fù)介紹_Android
- 2022-09-26 React 函數(shù)式組件怎樣進(jìn)行優(yōu)化
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門(mén)
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支