使用 dropout and/or 批量归一化的 PyTorch 训练
PyTorch training with dropout and/or batch-normalization
通过调用 model.eval()
.
在获得模型输出之前,我们是否还需要在训练期间执行此操作?如果网络包含一个或多个 dropout and/or batch-normalization 层,就像在训练时期内一样。
如果不这样做,那么训练时期前向传递的输出可能会受到 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()
例如,这里有一个要查看的示例代码:convolutional_neural_network/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()
TLDR:
Should this instead be?
没有!
Why?
更多解释:
不同模块的行为不同,具体取决于它们是处于训练模式还是 evaluation/test 模式。
BatchNorm
和 Dropout
只是此类模块的两个示例,基本上任何具有训练阶段的模块都遵循此规则。
当您执行 .eval()
时,您是在向模型中的所有模块发出信号以相应地转移操作。
更新
答案是在训练期间你不应该使用 eval
模式,是的,只要你没有设置 eval 模式,dropout 就会激活并在每次前向传播中随机行动。同样,所有其他具有两个阶段的模块都将相应地执行。也就是说,BN 将始终为每次传递更新 mean/var,而且如果您使用 1 的 batch_size,它会出错,因为它不能对 1
的批次执行 BN
正如评论中指出的那样,应该注意在训练期间,你不应该在前向传球之前做eval()
,因为它有效地禁用了所有对于 train/test 模式具有不同阶段的模块,例如 BN 和 Dropout(基本上任何具有 updateable/learnable 参数或影响网络拓扑的模块,如 dropout)将被禁用,您不会看到它们对您的网络有贡献学习。所以不要那样编码!
让我解释一下训练过程中发生的事情:
当您处于训练模式时,构成模型的所有模块可能有两种模式,即训练模式和测试模式。这些模块要么具有需要在训练期间更新的可学习参数,如 BN,要么在某种意义上影响网络拓扑,如 Dropout(通过在前向传递期间禁用某些功能)。一些模块如 ReLU() 只在一种模式下运行,因此当模式改变时不会有任何变化。
当你处于训练模式时,你输入一张图像,它通过多个层直到它面临一个 dropout,在这里,一些特征被禁用,因此对下一层的响应被省略,输出进入其他层直到它到达终点的网络,你会得到一个预测。
网络可能有正确或错误的预测,这将相应地更新权重。如果答案是正确的,则导致正确答案的 features/combinations 特征将受到积极影响,反之亦然。
所以在训练期间你不需要也不应该禁用 dropout,因为它会影响输出并且应该影响它以便模型学习一组更好的特征。
我希望这能让你更清楚一点。如果您仍然觉得还需要更多,请在评论中说出来。
model.eval()
.
在获得模型输出之前,我们是否还需要在训练期间执行此操作?如果网络包含一个或多个 dropout and/or batch-normalization 层,就像在训练时期内一样。
如果不这样做,那么训练时期前向传递的输出可能会受到 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()
例如,这里有一个要查看的示例代码:convolutional_neural_network/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()
TLDR:
Should this instead be?
没有!
Why?
更多解释:
不同模块的行为不同,具体取决于它们是处于训练模式还是 evaluation/test 模式。
BatchNorm
和 Dropout
只是此类模块的两个示例,基本上任何具有训练阶段的模块都遵循此规则。
当您执行 .eval()
时,您是在向模型中的所有模块发出信号以相应地转移操作。
更新
答案是在训练期间你不应该使用 eval
模式,是的,只要你没有设置 eval 模式,dropout 就会激活并在每次前向传播中随机行动。同样,所有其他具有两个阶段的模块都将相应地执行。也就是说,BN 将始终为每次传递更新 mean/var,而且如果您使用 1 的 batch_size,它会出错,因为它不能对 1
正如评论中指出的那样,应该注意在训练期间,你不应该在前向传球之前做eval()
,因为它有效地禁用了所有对于 train/test 模式具有不同阶段的模块,例如 BN 和 Dropout(基本上任何具有 updateable/learnable 参数或影响网络拓扑的模块,如 dropout)将被禁用,您不会看到它们对您的网络有贡献学习。所以不要那样编码!
让我解释一下训练过程中发生的事情:
当您处于训练模式时,构成模型的所有模块可能有两种模式,即训练模式和测试模式。这些模块要么具有需要在训练期间更新的可学习参数,如 BN,要么在某种意义上影响网络拓扑,如 Dropout(通过在前向传递期间禁用某些功能)。一些模块如 ReLU() 只在一种模式下运行,因此当模式改变时不会有任何变化。
当你处于训练模式时,你输入一张图像,它通过多个层直到它面临一个 dropout,在这里,一些特征被禁用,因此对下一层的响应被省略,输出进入其他层直到它到达终点的网络,你会得到一个预测。
网络可能有正确或错误的预测,这将相应地更新权重。如果答案是正确的,则导致正确答案的 features/combinations 特征将受到积极影响,反之亦然。 所以在训练期间你不需要也不应该禁用 dropout,因为它会影响输出并且应该影响它以便模型学习一组更好的特征。
我希望这能让你更清楚一点。如果您仍然觉得还需要更多,请在评论中说出来。