如何在 Pytorch 中实现 dropout,以及在哪里应用它

Posted

技术标签:

【中文标题】如何在 Pytorch 中实现 dropout,以及在哪里应用它【英文标题】:How to implement dropout in Pytorch, and where to apply it 【发布时间】:2020-03-19 01:52:02 【问题描述】:

我很不确定这是否正确。真的很难过,我找不到很多关于如何参数化 NN 的好例子。

您如何看待这两个班级的这种辍学方式。首先,我正在编写原始类:

class NeuralNet(nn.Module):
  def __init__(self, input_size, hidden_size, num_classes, p = dropout):
      super(NeuralNet, self).__init__()
      self.fc1 = nn.Linear(input_size, hidden_size)
      self.fc2 = nn.Linear(hidden_size, hidden_size)
      self.fc3 = nn.Linear(hidden_size, num_classes)

  def forward(self, x):
      out = F.relu(self.fc1(x))
      out = F.relu(self.fc2(out))
      out = self.fc3(out)
      return out

然后在这里,我发现了两种不同的写东西的方式,我不知道如何区分。第一个使用:

self.drop_layer = nn.Dropout(p=p) 

而第二个:

self.dropout = nn.Dropout(p) 

这是我的结果:

class NeuralNet(nn.Module):
  def __init__(self, input_size, hidden_size, num_classes, p = dropout):
      super(NeuralNet, self).__init__()
      self.fc1 = nn.Linear(input_size, hidden_size)
      self.fc2 = nn.Linear(hidden_size, hidden_size)
      self.fc3 = nn.Linear(hidden_size, num_classes)
      self.drop_layer = nn.Dropout(p=p)

  def forward(self, x):
      out = F.relu(self.fc1(x))
      out = F.relu(self.fc2(out))
      out = self.fc3(out)
      return out


 class NeuralNet(nn.Module):
  def __init__(self, input_size, hidden_size, num_classes, p = dropout):
      super(NeuralNet, self).__init__()
      self.fc1 = nn.Linear(input_size, hidden_size)
      self.fc2 = nn.Linear(hidden_size, hidden_size)
      self.fc3 = nn.Linear(hidden_size, num_classes)
      self.dropout = nn.Dropout(p) 

  def forward(self, x):
      out = F.relu(self.fc1(x))
      out = F.relu(self.fc2(out))
      out = self.fc3(out)
      return out

如果不是如何改进它,这是否可行,它是否给了我我期望的结果,这意味着创建一个神经网络,我可以在其中丢弃一些神经元。 重要的细节,我只想丢掉第二层神经网络,其余的不碰!

【问题讨论】:

我很高兴看到这么多关于这个问题的观点,如果你喜欢我的问题,请点个赞!我正在努力赚取积分 【参考方案1】:

您提供的两个示例完全相同。 self.drop_layer = nn.Dropout(p=p)self.dropout = nn.Dropout(p) 的不同之处仅在于作者将图层分配给了不同的变量名称。 dropout 层通常在.__init__() 方法中定义,并在.forward() 中调用。像这样:

 class NeuralNet(nn.Module):
  def __init__(self, input_size, hidden_size, num_classes, p = dropout):
      super(NeuralNet, self).__init__()
      self.fc1 = nn.Linear(input_size, hidden_size)
      self.fc2 = nn.Linear(hidden_size, hidden_size)
      self.fc3 = nn.Linear(hidden_size, num_classes)
      self.dropout = nn.Dropout(p) 

  def forward(self, x):
      out = F.relu(self.fc1(x))
      out = F.relu(self.fc2(out))
      out = self.dropout(self.fc3(out))
      return out

你可以做测试:

import torch
import torch.nn  as nn

m = nn.Dropout(p=0.5)
input = torch.randn(20, 16)
print(torch.sum(torch.nonzero(input)))
print(torch.sum(torch.nonzero(m(input))))
tensor(5440) # sum of nonzero values
tensor(2656) # sum on nonzero values after dropout

让我们想象一下:

import torch
import torch.nn as nn
input = torch.randn(5, 5)
print(input)
tensor([[ 1.1404,  0.2102, -0.1237,  0.4240,  0.0174],
        [-2.0872,  1.2790,  0.7804, -0.0962, -0.9730],
        [ 0.4788, -1.3408,  0.0483,  2.4125, -1.2463],
        [ 1.5761,  0.3592,  0.2302,  1.3980,  0.0154],
        [-0.4308,  0.2484,  0.8584,  0.1689, -1.3607]])

现在,让我们应用 dropout:

m = nn.Dropout(p=0.5)
output = m(input)
print(output)
tensor([[ 0.0000,  0.0000, -0.0000,  0.8481,  0.0000],
        [-0.0000,  0.0000,  1.5608, -0.0000, -1.9459],
        [ 0.0000, -0.0000,  0.0000,  0.0000, -0.0000],
        [ 0.0000,  0.7184,  0.4604,  2.7959,  0.0308],
        [-0.0000,  0.0000,  0.0000,  0.0000, -0.0000]])

大约有 一半 神经元已被归零,因为我们有概率 p=0.5 将神经元设置为零!

【讨论】:

我没用过 F. 方法,但是 nn.它有什么不同吗?所以我应该添加你写的那行?它会在隐藏层内造成dropout吗? 抱歉是一样的。我改变了它。是的,是的。看看我的编辑。你可以自己做测试。 谢谢尼古拉斯。只是那个小东西,因为我无法理解它:你如何测试自己?我得到的输出是“tensor5440”。那是什么意思 ?你写了“非零值的总和”,我不明白它的意思。我的输出也是 5440 和 2450。 一个 dropout 层将一定数量的神经元设置为零。我们传递的参数p=0.5 是任何神经元设置为零的概率。所以每次我们运行代码时,非零值的总和应该大约减少一半。想象一个大小为 5x5 的 2d 矩阵,其中填充了 1。非零值的总和为5*5=25。在 dropout 之后,大约一半的 1 将变为 0。因此非零值的总和将在 12 左右。

以上是关于如何在 Pytorch 中实现 dropout,以及在哪里应用它的主要内容,如果未能解决你的问题,请参考以下文章

如何在pytorch中实现可微的汉明损失?

如何在 Keras 模型中实现一些可训练的参数,例如 Pytorch 中的 nn.Parameters()?

Pytorch中nn.Dropout2d的作用

在Pytorch中实现相同的卷积

pytorch Dropout:“通道将独立清零”

在 Pytorch 中使用 Dropout:nn.Dropout 与 F.dropout