应通过调用将模型设置为评估模式以进行推理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()
例如这里是一个示例代码: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()
域名注册地址:
应该是这样吗?
不!
为什么?
更多解释:
不同模块的行为取决于它们是处于训练模式还是评估/测试模式。
BatchNorm
并且Dropout
只是此类模块的两个示例,基本上任何具有训练阶段的模块都遵循此规则。
当您这样做时.eval()
,您正在向模型中的所有模块发出信号以相应地转移操作。
更新
答案是在训练期间你不应该使用eval
模式,是的,只要你没有设置 eval 模式,dropout 就会在每次前传中处于活动状态并随机行动。类似地,具有两个阶段的所有其他模块将相应地执行。也就是说 BN 将始终更新每次传递的均值/无功,而且如果您使用 1 的 batch_size,它会出错,因为它不能用 1 的批次进行 BN
正如评论中指出的那样,应该注意的是,在训练期间,您不应该在前向传递eval()
之前进行,因为它有效地禁用了所有具有不同训练/测试模式阶段的模块,例如 BN 和 Dropout(基本上任何模块具有可更新/可学习的参数,或影响网络拓扑(如辍学)将被禁用,您将看不到它们对您的网络学习有贡献。所以不要这样编码!
让我解释一下训练期间会发生什么:
当您处于训练模式时,构成模型的所有模块可能有两种模式,训练模式和测试模式。这些模块要么具有需要在训练期间更新的可学习参数,如 BN,要么在某种意义上影响网络拓扑,如 Dropout(通过在前向传递期间禁用某些功能)。一些模块如 ReLU() 只在一种模式下运行,因此在模式改变时不会有任何变化。
当您处于训练模式时,您输入一个图像,它通过低谷层直到它面临 dropout 并且在这里,一些特征被禁用,因此对下一层的响应被省略,输出进入其他层,直到它到达最后网络,你会得到一个预测。
网络可能有正确或错误的预测,这将相应地更新权重。如果答案是正确的,则导致正确答案的特征/特征组合将受到积极影响,反之亦然。因此,在训练期间,您不需要也不应该禁用 dropout,因为它会影响输出并且应该会影响它,以便模型学习一组更好的特征。
我希望这能让你更清楚一点。如果您仍然觉得需要更多,请在评论中说出来。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句