首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >毕火炬: nn.Dropout与F.dropout

毕火炬: nn.Dropout与F.dropout
EN

Stack Overflow用户
提问于 2018-11-21 19:44:26
回答 3查看 86.9K关注 0票数 64

退学有两种方式:

  • torch.nn.Dropout
  • torch.nn.functional.Dropout

我问:

  • 他们之间有什么区别吗?
  • 我什么时候应该用一个而另一个呢?

当我把他们调换时,我看不出有什么表现上的差别。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-11-23 20:53:12

技术上的差异已经在另一个答案中显示出来了。然而,主要的区别在于,nn.Dropout本身就是一个火炬模块,具有一些方便性:

一个简短的例子来说明一些不同之处:

代码语言:javascript
运行
复制
import torch
import torch.nn as nn

class Model1(nn.Module):
    # Model 1 using functional dropout
    def __init__(self, p=0.0):
        super().__init__()
        self.p = p

    def forward(self, inputs):
        return nn.functional.dropout(inputs, p=self.p, training=True)

class Model2(nn.Module):
    # Model 2 using dropout module
    def __init__(self, p=0.0):
        super().__init__()
        self.drop_layer = nn.Dropout(p=p)

    def forward(self, inputs):
        return self.drop_layer(inputs)
model1 = Model1(p=0.5) # functional dropout 
model2 = Model2(p=0.5) # dropout module

# creating inputs
inputs = torch.rand(10)
# forwarding inputs in train mode
print('Normal (train) model:')
print('Model 1', model1(inputs))
print('Model 2', model2(inputs))
print()

# switching to eval mode
model1.eval()
model2.eval()

# forwarding inputs in evaluation mode
print('Evaluation mode:')
print('Model 1', model1(inputs))
print('Model 2', model2(inputs))
# show model summary
print('Print summary:')
print(model1)
print(model2)

输出:

代码语言:javascript
运行
复制
Normal (train) model:
Model 1 tensor([ 1.5040,  0.0000,  0.0000,  0.8563,  0.0000,  0.0000,  1.5951,
         0.0000,  0.0000,  0.0946])
Model 2 tensor([ 0.0000,  0.3713,  1.9303,  0.0000,  0.0000,  0.3574,  0.0000,
         1.1273,  1.5818,  0.0946])

Evaluation mode:
Model 1 tensor([ 0.0000,  0.3713,  0.0000,  0.0000,  0.0000,  0.0000,  0.0000,
         0.0000,  0.0000,  0.0000])
Model 2 tensor([ 0.7520,  0.1857,  0.9651,  0.4281,  0.7883,  0.1787,  0.7975,
         0.5636,  0.7909,  0.0473])
Print summary:
Model1()
Model2(
  (drop_layer): Dropout(p=0.5)
)

,那么我应该使用哪种?

两者在应用辍学方面是完全相同的,尽管使用上的差异并不大,但有一些理由支持nn.Dropout over nn.functional.dropout

辍学被设计为只适用于培训,所以当你做预测或评估模型时,你希望辍学被关闭。

退出模块nn.Dropout可以方便地处理这一问题,并在模型进入评估模式时立即关闭退出,而函数退出则不关心评估/预测模式。

即使您可以将函数下拉设置为training=False来关闭它,但它仍然不是一个像nn.Dropout那样方便的解决方案。

另外,下降率存储在模块中,因此不必将其保存在额外的变量中。在更大的网络中,您可能希望创建不同的下拉层,在这里,nn.Dropout可能会增加可读性,并且在多次使用这些层时也能承受一些方便。

最后,分配给您的模型的所有模块都在您的模型中注册。因此,模型类可以跟踪它们,这就是为什么您可以通过调用eval()来关闭退出模块。当使用函数下拉时,您的模型不知道它,因此它不会出现在任何摘要中。

票数 92
EN

Stack Overflow用户

发布于 2018-11-21 20:32:41

如果您查看nn.DropoutFunctional.Dropout的源代码,可以看到Functional是一个接口,nn模块实现了与该接口相关的函数。

查看nn类中的实现:

代码语言:javascript
运行
复制
from .. import functional as F
class Dropout(_DropoutNd):
    def forward(self, input):
        return F.dropout(input, self.p, self.training, self.inplace)

class Dropout2d(_DropoutNd):
    def forward(self, input):
        return F.dropout2d(input, self.p, self.training, self.inplace)

诸若此类。

Functional类的实现:

代码语言:javascript
运行
复制
def dropout(input, p=0.5, training=False, inplace=False):
    return _functions.dropout.Dropout.apply(input, p, training, inplace)

def dropout2d(input, p=0.5, training=False, inplace=False):
    return _functions.dropout.FeatureDropout.apply(input, p, training, inplace)

请看下面的示例以了解:

代码语言:javascript
运行
复制
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(1, 10, kernel_size=5)
        self.conv2 = nn.Conv2d(10, 20, kernel_size=5)
        self.conv2_drop = nn.Dropout2d()
        self.fc1 = nn.Linear(320, 50)
        self.fc2 = nn.Linear(50, 10)

    def forward(self, x):
        x = F.relu(F.max_pool2d(self.conv1(x), 2))
        x = F.relu(F.max_pool2d(self.conv2_drop(self.conv2(x)), 2))
        x = x.view(-1, 320)
        x = F.relu(self.fc1(x))
        x = F.dropout(x, training=self.training)
        x = self.fc2(x)
        return F.log_softmax(x)

F.dropoutforward()函数中有一个nn.Dropout__init__()函数中。这就是解释:

在PyTorch中,您将模型定义为torch.nn.Module的子类。

init函数中,您应该初始化要使用的层。与keras不同,Py手电的级别更低,您必须指定网络的大小,以便所有的内容都匹配。

在正向方法中,指定层的连接。这意味着您将使用您已经初始化的层,以便为您所做的每一次前向传递重新使用相同的层。

torch.nn.Functional包含一些有用的函数,比如激活函数、卷积操作。但是,这些不是完整的层,所以如果您想指定任何类型的层,则应该使用torch.nn.Module。

您可以使用torch.nn.Functional conv操作来定义自定义层--例如,使用卷积操作,而不是定义标准卷积层。

票数 11
EN

Stack Overflow用户

发布于 2019-05-20 14:38:49

检查torch.nn.functional的实现:

代码语言:javascript
运行
复制
 if p < 0. or p > 1.:
        raise ValueError("dropout probability has to be between 0 and 1, "
                         "but got {}".format(p))
    return (_VF.dropout_(input, p, training)
            if inplace
            else _VF.dropout(input, p, training))

检查:torch.nn.dropout的实现:

代码语言:javascript
运行
复制
def forward(self, input):
        return F.dropout(input, self.p, self.training, self.inplace)

所以:他们的内部运作是一样的。界面是不同的。至于_VF,我猜这是一些C/C++代码。

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

https://stackoverflow.com/questions/53419474

复制
相关文章

相似问题

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