如何理解Pytorch中前向传播的计算过程
我们经常在进行编写训练过程的时候,直接利用model(data)
来计算预测结果,形式很方便简介,一个例子如下:
model = Simple_Module()
# 训练过程
for epoch in range(num_epochs): # 训练 100 轮model.train() # 训练模式optimizer.zero_grad() # 清除梯度Y_pred = model(X) # 前向传播loss = criterion(Y_pred, Y) # 计算损失loss.backward() # 反向传播optimizer.step() # 更新权重
但是,实际上还是走了一段“路程”。我们在使用model(X)
来计算预测结果的时候,看上去很像是把model
当一个函数取调用,那X
是导入的数据参数。实际上,model(X)
的实现靠的是model.forward(X)
,当然Python屏蔽了其中的过程。
那如何做到向使用函数一样计算出预测结果呢?答案是__call__
方法
任何一个深度学习模块都是基于父类nn.Module
实现的,上文中Simple_Module
也不例外。所以应该看看nn.Module
。
class Module:def __call__(self, *input, **kwargs):# 1. 前向传播前的钩子(Pre-Forward Hooks)pass# 2. 执行用户定义的 forward 方法result = self.forward(*input, **kwargs)# 3. 前向传播后的钩子(Post-Forward Hooks)pass# 4. 返回结果return result
显然,nn.Module
中定义了 __call__()
方法,那么它的实例就可以被当作函数使用。
那为什么需要用__call__()
?
1 就是让用户向使用函数一样,来获取到预测结果,譬如Y_pred = model(X)
2 __call__()
是 PyTorch 控制模型执行流程的关键钩子点
因为,我们不仅仅是需要让模型像函数一样来计算预测结果,我们还需要考虑到整个训练和推理的需求,例如自动求导、前向/后向 hook、模型并行机制、混合精度支持等等。但是这些又不需要对用户呈现