首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >毕火炬:“模型权重不变”

毕火炬:“模型权重不变”
EN

Stack Overflow用户
提问于 2018-11-24 19:57:18
回答 2查看 2.3K关注 0票数 1

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

代码语言:javascript
复制
    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]) # weights of the first layer in the unet
    loss.backward()
    optimizer.step()
    print(unet.conv1.weight.data[0][0]) # weights havent changed

该模型的定义如下:

代码语言:javascript
复制
class Unet(nn.Module):

def __init__(self):
  super(Unet, self).__init__()

  # Down hill1
  self.conv1 = nn.Conv3d(1, 2, kernel_size=3,  stride=1)
  self.conv2 = nn.Conv3d(2, 2, kernel_size=3,  stride=1)

  # Down hill2
  self.conv3 = nn.Conv3d(2, 4, kernel_size=3,  stride=1)
  self.conv4 = nn.Conv3d(4, 4, kernel_size=3,  stride=1)

  #bottom
  self.convbottom1 = nn.Conv3d(4, 8, kernel_size=3,  stride=1)
  self.convbottom2 = nn.Conv3d(8, 8, kernel_size=3,  stride=1)

  #up hill1
  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)

  #up hill2
  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)
  # some more irrelevant properties...

前向函数如下所示:

代码语言:javascript
复制
def forward(self, input):
    # Use U-net Theory to Update the filters.
    # Example Approach...
    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是空的,这是不应该的。如果我们没有梯度,那么优化器当然不能在任何方向改变权重,但是为什么没有梯度呢?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-03-06 16:54:33

我认为这个问题是“垂死的ReLu问题”,因为数据是Hounsfield单位,并且初始权重的Pytorch均匀分布意味着许多神经元从ReLu的零区域开始,使它们瘫痪并依赖于其他神经元,从而产生一个梯度,将它们从零区域拉出。随着训练的进行,这种情况不太可能发生--所有的神经元都会被推入雷鲁的零区域。

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

您还可以使用批处理规范化输入数据,并初始化权重,使之仅为正类型。

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

对于Hounsfield数据,还可以在输入数据中添加一个1000的常数,以消除数据中的负单位。这仍然需要不同的权值初始化,而不是毕火炬的标准初始化。

票数 3
EN

Stack Overflow用户

发布于 2018-11-24 21:29:18

我不认为重量应该用你使用的命令打印。尝试print(unet.conv1.state_dict()["weight"])而不是print(unet.conv1.weight.data[0][0])

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53461869

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档