Pytorch: “模型权重未更新”

有人可以帮助我理解为什么权重没有更新吗?

    unet = Unet()    optimizer = torch.optim.Adam(unet.parameters(), lr=0.001)    loss_fn = torch.nn.MSELoss()    input =  Variable(torch.randn(32, 1, 64, 64, 64 ), requires_grad=True)    target = Variable(torch.randn(32, 1, 64, 64, 64), requires_grad=False)    optimizer.zero_grad()    y_pred = unet(input)    y = target[: , : , 20:44, 20:44, 20:44]    loss = loss_fn(y_pred, y)    print(unet.conv1.weight.data[0][0]) # 打印Unet第一层的权重    loss.backward()    optimizer.step()    print(unet.conv1.weight.data[0][0]) # 权重没有变化

模型定义如下:

class Unet(nn.Module):def __init__(self):  super(Unet, self).__init__()  # 下行路径1  self.conv1 = nn.Conv3d(1, 2, kernel_size=3,  stride=1)  self.conv2 = nn.Conv3d(2, 2, kernel_size=3,  stride=1)  # 下行路径2  self.conv3 = nn.Conv3d(2, 4, kernel_size=3,  stride=1)  self.conv4 = nn.Conv3d(4, 4, kernel_size=3,  stride=1)  # 底部  self.convbottom1 = nn.Conv3d(4, 8, kernel_size=3,  stride=1)  self.convbottom2 = nn.Conv3d(8, 8, kernel_size=3,  stride=1)  # 上行路径1  self.upConv0 = nn.Conv3d(8, 4, kernel_size=3,  stride=1)  self.upConv1 = nn.Conv3d(4, 4, kernel_size=3,  stride=1)  self.upConv2 = nn.Conv3d(4, 2, kernel_size=3,  stride=1)  # 上行路径2  self.upConv3 = nn.Conv3d(2, 2, kernel_size=3, stride=1)  self.upConv4 = nn.Conv3d(2, 1, kernel_size=1, stride=1)  self.mp = nn.MaxPool3d(kernel_size=3, stride=2, padding=1)  # 其他不相关的属性...

前向函数如下:

def forward(self, input):    # 使用U-net理论更新滤波器。    # 示例方法...    input = F.relu(self.conv1(input))    input = F.relu(self.conv2(input))    input = self.mp(input)    input = F.relu(self.conv3(input))    input = F.relu(self.conv4(input))    input = self.mp(input)    input = F.relu(self.convbottom1(input))    input = F.relu(self.convbottom2(input))    input = F.interpolate(input, scale_factor=2, mode='trilinear')    input = F.relu(self.upConv0(input))    input = F.relu(self.upConv1(input))    input = F.interpolate(input, scale_factor=2, mode='trilinear')    input = F.relu(self.upConv2(input))    input = F.relu(self.upConv3(input))    input = F.relu(self.upConv4(input))    return input

我已经按照我能找到的所有示例和文档的方法进行操作,但我无法理解为什么它不起作用?

我发现y_pred.grad在反向传播调用后为None,这是不应该的。如果没有梯度,当然优化器无法在任何方向上改变权重,但为什么没有梯度呢?


回答:

我发现这个问题是“ReLU死亡问题”导致的。由于数据是豪斯菲尔德单位,而Pytorch的权重初始化的均匀分布意味着许多神经元会从ReLU的零区域开始,使它们瘫痪并依赖其他神经元产生能够将它们拉出零区域的梯度。这种情况在训练过程中不太可能发生,因为所有神经元都会被推入ReLU的零区域。

这个问题有几个解决方案。你可以使用Leaky_relu或其他没有零区域的激活函数。

你也可以使用批量归一化来标准化输入数据,并将权重初始化为仅正值。

第二种解决方案可能是最优的,因为两者都能解决问题,但Leaky_relu会延长训练时间,而批量归一化则会起到相反的作用,提高准确性。另一方面,Leaky_relu是一个简单的修复方案,而另一种解决方案需要额外的工作。

对于豪斯菲尔德数据,还可以将常数1000添加到输入中,以消除数据中的负单位。这仍然需要不同于Pytorch标准初始化的权重初始化。

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注