在阅读一些深度学习项目的代码中,我们会发现这样一个问题,深度学习网络模型中常常要定义
forward()
方法,但是在使用该函数时却没有显式地调用函数的forward()
,却好像“自动”地执行了。
比如下面这个例子(不可执行的代码,仅描述常见网络模型的大致定义框架、模型实例化和获取输出的过程),实例化网络模型后并没有调用forward()
函数,却执行forward()
处理了输入,并得到了输出结果,这是为什么呢?让我们一起来探索吧!
class Model(nn.Module):
def __init__(self):
super(Model,self).__init__()
```
网络定义部分
```
def forward(self,输入):
```
前向传播部分
```
return 处理后的输入
#实例化网络模型
model = Model()
输出 = model(输入)
一、答案揭晓
答案就在于Model()
类继承自nn.Module
,nn.Module
中定义了__call__
函数,而在__call__
函数中又调用了forward()
方法,然后因为Model()
类重写了forward()
方法,所以看起来就好像自动调用了重写后的forward()
方法。
那么接下来,就让我们一起看看__call__
函数的使用!
二、_ _call _ _
来看这样一个例子:
class Cat():
def __call__(self, name):
print("小猫的名字叫",name)
def eat(self, food):
print("小猫要吃",food)
miao = Cat()
miao('miao')
miao.eat('fish')
输出:
小猫的名字叫 miao
小猫要吃 fish
在这个例子中,我们能看出来,__call__
的调用可以直接用实例化对象名调用,而不需要写成对象.__call__()
的形式。
三、_ _call _ _与forward()
本来想看看nn.Module
中__call__
具体是怎样调用forward()
函数的,但是点开nn.Module
,代码简直太复杂了,读不懂一点,所以我们采用下面这样一个例子来大概展现下,__call__
是如何自动调用forward()
函数的。
# 类比class Model()
class Baby():
def __init__(self, init_age=1):
self.age = init_age
print('init实现——我的初始年龄是:', self.age)
def __call__(self, added_age):
print('call实现——我增加的年龄是:', added_age)
age = self.forward(added_age)
return age
def forward(self, added_age):
self.age = self.age + added_age
print('forward实现——我最终的年龄是:', self.age)
return self.age
# 类比model = Model()
baby = Baby()
# 类比output = model(input)
age = baby(2)
print('最终结果——我最终的年龄是:', age)
输出:
init实现——我的初始年龄是: 1
call实现——我增加的年龄是: 2
forward实现——我最终的年龄是: 3
最终结果——我最终的年龄是: 3
通过这个例子,我们能够学习到,在进行实例化后,__call__()
可以直接用实例化对象名调用,然后在__call__()
中又调用了forward()
,因此用实例化对象名可以直接得到forward()
的输出赋值给最终的age
。
相信通过这几个例子,能够让我们对于__call__
以及forward()
有了更深的理解了,到实践中去检验它们吧~
写在后面
这个专栏主要是我在实现深度学习项目中总结的一些问题,以备未来笔试和面试之需,不过由于学习的不深入,也只是走马观花,很多问题总结得也不是很透彻,望读者见谅,如果有错误和不足之处,还望大家在评论区指出。希望能给大家的学习带来一点帮助,共同进步!!!