PyTorch 自定义卷积模板,backward 报错 RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation
问题,如题目所述
主要原因是 Tensor 变量有 “就地更改” 的,比如 ReLU(inplace=True),或者有 +=, -= 操作符,需要声明新的变量并赋值。自己的问题主要是在 slice 切片时产生的。
原代码
在 batch_size 维度进行图像归一化时,由 x_out[i] = x_out[i] - ** 引发,可能是切片操作指向的引用发生了 “就地更改” 。
def forward(self, x):
"""默认输入三通道图像, [B,C,H,W]"""
batch_size, in_channels, H, W = x.size()[:]
conv_groups = in_channels # 这里默认 group 单通道分离,不然出来是灰度图
kernel_ = self.kernel.repeat(in_channels, in_channels // conv_groups, 1, 1)
weight_ = nn.Parameter(data=kernel_, requires_grad=False)
x_out = F.conv2d(input=x, weight=weight_, padding=2, groups=conv_groups)
# x_out = nn.Conv2d(in_channels, in_channels, 3, padding=2, groups=conv_groups)(x)
# for i in range(batch_size):
# x_out[i] = x_out[i] - torch.min(x_out[i]) # not inplace, cannot use -=
# x_out[i] = x_out[i] / torch.max(x_out[i]) # max(x - min) = max_x - min_x
# x_out[i] = torch.mul(x_out[i], self.alpha) # 拉伸后亮一些
return x_out
更正方案一
声明新的变量再赋值,避免 inplace 操作。
nor_list = []
for i in range(batch_size):
nor_ = x_out[i] - torch.min(x_out[i])
nor_ = nor_ / torch.max(nor_)
nor_ = torch.mul(nor_, self.alpha)
nor_list.append(nor_)
x_nor = torch.cat(nor_list, dim=0)
if (batch_size == 1):
x_nor = x_nor.unsqueeze(0)
更正方案二
采用广播机制,去掉 for 循环,相对更优雅。
x_out = torch.reshape(x_out, (batch_size, -1))
x_nor = x_out - torch.min(x_out, 1, keepdim=True)[0]
x_nor = x_nor / torch.max(x_nor, 1, keepdim=True)[0]
x_nor = torch.reshape(x_nor, (batch_size, in_channels, H, W))
x_nor = torch.mul(x_nor, self.alpha)