使用 dropout 和/或批量归一化进行 PyTorch 训练

问题描述 投票:0回答:1

应通过调用model.eval()

将模型设置为评估模式以进行推理

在获得模型输出之前,我们是否还需要在训练期间执行此操作?就像在训练时期内,如果网络包含一个或多个 dropout 和/或批量归一化层。

如果不这样做,那么训练时期的前向传递的输出可能会受到 dropout 随机性的影响?

许多示例代码都没有这样做,常见的方法是:

for t in range(num_epochs):
    # forward pass
    yhat = model(x)
  
    # get the loss
    loss = criterion(yhat , y)
    
    # backward pass, optimizer step
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

例如,这里有一个示例代码:卷积神经网络/main.py

这应该是吗?

for t in range(num_epochs):
    # forward pass
    model.eval() # disable dropout etc
    yhat = model(x)
    
    # get the loss
    loss = criterion(yhat , y)
    
    # backward pass, optimizer step
    model.train()
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
pytorch batch-normalization dropout
1个回答
2
投票

TLDR:

这应该是吗?

不!

为什么?

更多说明:
不同的模块根据是否处于训练模式或评估/测试模式而表现不同。

BatchNorm
Dropout
只是此类模块的两个示例,基本上任何具有训练阶段的模块都遵循此规则。
当您执行
.eval()
时,您就向模型中的所有模块发出信号以相应地转移操作。

更新
答案是在训练期间你不应该使用

eval
模式,是的,只要你没有设置 eval 模式,dropout 就会处于活动状态并在每次前向传递中随机动作。同样,具有两个阶段的所有其他模块也将相应地执行。也就是说,BN 总是会更新每次传递的平均值/var,而且如果您使用的 batch_size 为 1,则会出错,因为它无法使用 1 的批次执行 BN

正如评论中指出的那样,应该注意的是,在训练期间,您不应该在

forward pass
之前执行eval(),因为它会有效地禁用具有不同阶段的训练/测试模式的所有模块,例如BN和Dropout(基本上任何具有可更新/可学习参数或影响网络拓扑(如 Dropout)的模块)将被禁用,您将不会看到它们对您的网络学习做出贡献。所以不要这样编码!

让我解释一下训练期间发生的事情:
当您处于训练模式时,构成模型的所有模块可能有两种模式:训练模式和测试模式。这些模块要么具有需要在训练期间更新的可学习参数,例如 BN,要么在某种意义上影响网络拓扑,例如 Dropout(通过在前向传递期间禁用某些功能)。有些模块(例如 ReLU())仅在一种模式下运行,因此当模式改变时不会有任何变化。
当您处于训练模式时,您输入图像,它通过槽层直到面临丢失,在这里,某些功能被禁用,因此省略了对下一层的响应,输出进入其他层直到到达结束网络,您就可以得到预测。

网络可能有正确或错误的预测,从而相应地更新权重。如果答案是正确的,则导致正确答案的特征/特征组合将受到积极影响,反之亦然。 因此,在训练期间,您不需要也不应该禁用 dropout,因为它会影响输出并且应该影响输出,以便模型学习一组更好的特征。

© www.soinside.com 2019 - 2024. All rights reserved.