在 PyTorch 中,dropout 可以以两种方式使用:一种是作为一个独立的函数 torch.nn.functional.dropout
,另一种是作为一个层 torch.nn.Dropout
。虽然它们在操作上是相似的,但它们在使用上有所不同。
dropout 函数 (torch.nn.functional.dropout
)
这是一个函数,直接调用时需要指定输入张量、dropout概率 p
,以及是否处于训练模式。使用函数版本时,你每次调用时都需要明确指出是否应用dropout。
import torch
import torch.nn.functional as F
# 输入张量
input = torch.randn(1, 3)
# 应用dropout函数
output = F.dropout(input, p=0.5, training=model.training)
在这个例子中,你必须手动提供 training
参数的值,以确定是否实际上要应用dropout操作。
在进行评估的时候,如果使用 dropout 函数而不是 Dropout 类,你需要手动确保 training 参数设置为 False 来避免在推理时应用 dropout。例如:
# 在推理时手动关闭dropout
output = dropout(input, p=0.5, training=False)
Dropout 类 (torch.nn.Dropout
)
这是一个模块,当你构造你的神经网络时,它可以作为一个层被添加到你的模型中。这个类的实例会根据模型的 training
状态自动应用或不应用dropout。
import torch
import torch.nn as nn
# 创建一个dropout层
dropout_layer = nn.Dropout(p=0.5)
# 输入张量
input = torch.randn(1, 3)
# 应用dropout层
output = dropout_layer(input)
在模型定义中通常会使用类版本,因为它与其他层一起,可以很容易地整合到 nn.Sequential
中,并且可以通过调用模型的 .train()
或 .eval()
方法自动切换训练模式或评估模式。
当模型被设置为 .eval()
模式时,所有的 nn.Dropout
层会知道不应该进行dropout操作。这与函数版本不同,你需要手动指定 training
参数。
model = nn.Sequential(
nn.Linear(3, 3),
nn.ReLU(),
nn.Dropout(p=0.5),
nn.Linear(3, 1)
)
# 切换到评估模式,关闭dropout
model.eval()
因此,在使用 nn.Dropout
类时,通常不需要在 with torch.no_grad():
上下文中手动设置 training
参数,因为 .eval()
方法已经为你做了这件事。
大模型里如果包裹着众多子模型,对大模型进行eval() 会递归让小模型的Dropout 类关闭training。
在 PyTorch 中,当你调用一个模型的 .eval() 方法时,它会递归地对所有子模块(包括所有的层和嵌套的子模型)设置为评估模式。这意味着所有的 nn.Dropout 层以及其他具有不同训练和评估行为的层(如 nn.BatchNorm 层)会被设置为评估模式,从而停用它们的训练特定行为。
nn.Dropout 的情况下是随机置零输出元素。