pytorch - loss.backward() 和 optimizer.step() 在 eval 模式下使用批量规范层?

pytorch - loss.backward() and optimizer.step() in eval mode with batch norm layers?

我有一个 ResNet-8 网络,用于 Domain Adaptation over images[= 的项目34=],基本上我已经在一个数据集上训练了网络,现在我想在另一个模拟实时环境的数据集上对其进行评估,我尝试一次预测一个图像,但有趣的部分来了:

我想对目标数据集进行评估的方法是,对于每张图像,在训练模式下进行前向传递,以便更新批量规范层统计信息(使用 torch.no_grad(),因为那时我不想更新网络参数,而只更新 "adapt" 批量规范层),然后在 eval 模式下进行另一次前向传递以获得实际预测,以便批量规范层将使用均值和基于到目前为止看到的整组图像的方差(不仅是那批图像,在这种情况下是单个图像):

optimizer.zero_grad()
model.train()
with torch.no_grad():
  output_train = model(inputs)
model.eval()
output_eval = model(inputs)
loss = criterion(output_eval, targets)

我的想法是 域自适应只是通过将批量规范层更新到新的目标分布

然后假设我的准确率为 60%。 现在,如果我添加另外两行,我就能达到 80% 的准确率:

loss.backward()
optimizer.step()

因此我的问题是 如果我在评估模式下执行 backward() 和 step() 会发生什么情况?因为我知道批规范和 dropout 层在训练和评估模式之间的不同行为,我知道 torch.no_grad() 以及梯度是如何计算的,然后由优化器更新参数,但我无法找到关于我的具体问题的任何信息。

我认为既然模型设置为eval模式,那么这两行应该是没用的,但显然发生了一些事情,这与batch norm层的仿射参数有关吗?

UPDATE:好的,我误解了一些东西:eval 模式不会阻止要更新的参数,它只会在前向传播过程中改变某些层的行为(batch norm 和 dropout) , 我对吗?因此,通过这两行,我实际上是在训练网络,因此准确性更高。无论如何,如果批规范仿射设置为真,这会改变什么吗?这些参数是否被视为要在 optimizer.step() 期间更新的 "normal" 参数还是不同?

eval mode does not block parameters to be updated, it only changes the behaviour of some layers (batch norm and dropout) during the forward pass, am I right?

正确。

Therefore with those two lines I am actually training the network, hence the better accuracy. Anyway does this change something if batch norm affine is set to true? Are those parameters considered as "normal" parameters to be updated during optimizer.step() or is it different?

BN 参数在优化器步骤中更新。看:

    if self.affine:
        self.weight = Parameter(torch.Tensor(num_features))
        self.bias = Parameter(torch.Tensor(num_features))
    else:
        self.register_parameter('weight', None)
        self.register_parameter('bias', None)