PyTorch中Residual Block前向传播函数的正确写法及两种实现对比
PyTorch中ResNet Block两种实现的差异与推荐写法
在PyTorch中实现ResNet Block常见两种写法:
- 第一种:先复制输入到临时变量,后续修改原输入变量,最后将临时变量与修改后的输入相加
- 第二种:保留原输入变量不变,后续基于原输入创建新变量处理,最后将原输入与新变量相加
对应两种代码实现如下:
def forward(self, x): y = x x = self.conv1(x) x = self.norm1(x) x = self.act1(x) x = self.conv2(x) x = self.norm2(x) x += y x = self.act2(x) return x
def forward(self, x): y = self.conv1(x) y = self.norm1(y) y = self.act1(y) y = self.conv2(y) y = self.norm2(y) y += x y = self.act2(y) return y
两种实现是否完全相同?
两种实现的计算逻辑完全一致,前向传播的输出结果没有差异,反向传播的梯度计算也不会有区别。
哪种写法更值得推荐?原因是什么?
更推荐第二种写法,原因如下:
- 语义清晰,可读性更强:原输入
x全程保持初始状态,y专门指代经过卷积、归一化等变换后的特征,代码逻辑一目了然,能让阅读者快速区分“原始输入”和“变换后的特征”。 - 降低调试风险:第一种写法中
x被反复赋值修改,如果后续代码需要用到原始输入,很容易误用到已经被修改后的x;而第二种写法中x始终是原始输入,不存在这类混淆问题。 - 符合PyTorch使用习惯:PyTorch通常倾向于保留原始输入张量的独立性,避免直接覆盖输入变量,即便这里的计算图不会受影响,但代码的可维护性和扩展性更好。
内容的提问来源于stack exchange,提问作者amp-likes-linux
相关产品推荐
相关产品推荐

