为什么 Keras BatchNorm 产生与 PyTorch 不同的输出?

call_me_ye

火炬:'1.9.0+cu111'

Tensorflow-gpu:'2.5.0'

我遇到了一个奇怪的事情,当使用tensorflow 2.5的Batch Normal层和Pytorch 1.9的BatchNorm2d层计算同一个Tensor时,结果相差很大(TensorFlow接近1,Pytorch接近0)。一开始以为是momentum和epsilon的区别,后来改成一样,结果是一样的。

from torch import nn
import torch
x = torch.ones((20, 100, 35, 45))
a = nn.Sequential(
            # nn.Conv2d(512, 128, kernel_size=(1, 1), stride=(1, 1), padding=0, bias=True),
            nn.BatchNorm2d(100)
        )
b = a(x)

import tensorflow as tf
import tensorflow.keras as keras
from tensorflow.keras.layers import *
x = tf.ones((20, 35, 45, 100))
a = keras.models.Sequential([
            # Conv2D(128, (1, 1), (1, 1), padding='same', use_bias=True),
            BatchNormalization()
        ])
b = a(x)

TensorFlow 的结果

Pytorch 的结果

扎比尔·阿尔·纳兹

批量归一化在训练和推理中的工作方式不同,

在训练期间(即使用fit()或调用带有参数的层/模型时training=True),层使用当前输入批次的均值和标准差对其输出进行归一化。也就是说,对于每个被归一化的通道,该层返回

gamma * (batch - mean(batch)) / sqrt(var(batch) + epsilon) + beta

在哪里:

  • epsilon是小常量(可配置为构造函数参数的一部分)
  • gamma是一个学习的缩放因子(初始化为 1),可以通过将 scale=False 传递给构造函数来禁用它。
  • beta是一个学习的偏移因子(初始化为 0),可以通过将 center=False 传递给构造函数来禁用它。

在推理过程中(即当使用evaluate()predict()当使用参数调用层/模型时training=False(这是默认值),层使用它在训练期间看到的批次的均值和标准差的移动平均值对其输出进行归一化。即说,它返回

gamma * (batch - self.moving_mean) / sqrt(self.moving_var + epsilon) + beta.

self.moving_meanself.moving_var是不可训练的变量,每次在训练模式下调用层时都会更新,例如:

    moving_mean = moving_mean * momentum + mean(batch) * (1 - momentum)
    moving_var = moving_var * momentum + var(batch) * (1 - momentum)

参考:https : //www.tensorflow.org/api_docs/python/tf/keras/layers/BatchNormalization

如果你在eval模式下运行 pytorch batchnorm ,你会得到接近的结果(其余的差异来自不同的内部实现、参数选择等),

from torch import nn
import torch
x = torch.ones((1, 2, 2, 2))
a = nn.Sequential(
            # nn.Conv2d(512, 128, kernel_size=(1, 1), stride=(1, 1), padding=0, bias=True),
            nn.BatchNorm2d(2)
        )
a.eval()
b = a(x)
print(b)
import tensorflow as tf
import tensorflow.keras as keras
from tensorflow.keras.layers import *
x = tf.ones((1, 2, 2, 2))
a = keras.models.Sequential([
            # Conv2D(128, (1, 1), (1, 1), padding='same', use_bias=True),
            BatchNormalization()
        ])
b = a(x)
print(b)

out:

tensor([[[[1.0000, 1.0000],
          [1.0000, 1.0000]],

         [[1.0000, 1.0000],
          [1.0000, 1.0000]]]], grad_fn=<NativeBatchNormBackward>)
tf.Tensor(
[[[[0.9995004 0.9995004]
   [0.9995004 0.9995004]]

  [[0.9995004 0.9995004]
   [0.9995004 0.9995004]]]], shape=(1, 2, 2, 2), dtype=float32)

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

为什么这些命令产生不同的输出?

Batchnorm2d Pytorch-为什么将通道数传递给Batchnorm?

Keras的BatchNormalization和PyTorch的BatchNorm2d之间的区别?

为什么使用PIL和pytorch对图像进行双线性缩放会产生不同的结果?

为什么tar输出上的gzip总是产生不同的结果?

为什么此PowerShell位操作产生的输出与Python不同?

为什么这个基本的Java代码会产生不同的输出?

总结为什么 keras 自定义层会产生无意义的输出形状

BatchNorm动量惯例PyTorch

为什么 keras Batchnorm 中只有一个动量参数?

为什么以两种不同的方式构建相同的模型会产生不同的输出?

线程基础:为什么同一代码在不同的类中产生不同的输出?

为什么 qsort 为相同的数组产生不同的输出但排序不同?

为什么结果与Keras模型中的调用和预测不同?似乎预测忽略任何随机产生的值

为什么“ printf”不产生任何输出?

为什么该程序产生输出

为什么ltrace不产生任何输出

为什么执行会产生错误的输出?

为什么括号会产生不同的答案?

为什么“ hexdec”产生不同的结果?

为什么这些PHP和Java密码生成器产生不同的输出?

为什么var和let在闭包中产生不同的输出?

为什么 tfa.layers.GroupNormalization(groups=1) 产生与 LayerNormalization 不同的输出?

为什么这两个rm命令产生不同的输出?

为什么即使我设置种子变量,TensorFlow也会产生不同的输出?

为什么这两个代码样本产生不同的输出?

为什么我极其基础的CSS代码在jsFiddle和jsBin上产生不同的输出?

为什么bash printf%q会产生不同种类的输出?

为什么在Visual Studio中构建和构建dotnet会产生不同的输出?