Python 禁用Keras批次标准中的移动平均值和标准

Python 禁用Keras批次标准中的移动平均值和标准,python,keras,Python,Keras,有没有办法让Keras在每个BatchNormalization层中分别计算每个批次的平均值和标准偏差,而不是对其进行训练(类似于PyTorch的做法) 更详细地说,Keras BatchNormalization层持有四组权重[伽马、贝塔、平均值、标准],并在每个批次上更新它们 PyTorchBatchNormal2D持有两组权重[gamma,beta],并计算每个批次的平均值和标准差: 我在这里发现了一个类似的问题: 但是它没有像我描述的那样设置功能(类似于Pytork)。Keras“确实”

有没有办法让Keras在每个
BatchNormalization
层中分别计算每个批次的平均值和标准偏差,而不是对其进行训练(类似于PyTorch的做法)

更详细地说,Keras BatchNormalization层持有四组权重
[伽马、贝塔、平均值、标准]
,并在每个批次上更新它们

PyTorch
BatchNormal2D
持有两组权重[gamma,beta],并计算每个批次的平均值和标准差:

我在这里发现了一个类似的问题: 但是它没有像我描述的那样设置功能(类似于Pytork)。

Keras“确实”在训练期间分别计算每批的平均值和标准偏差

这些值没有像其他两个值那样经过训练。它们只是“积累”。(累积值仅用于预测/推断)

这就是为什么
BatchNormalization
层的一半参数在模型摘要中显示为“不可训练参数”。(因此,当假设Pytork没有这些时要小心——我不知道Pytork层,如果你知道的话,请“深入”忽略这些括号——因为它们不是通过反向传播“可训练的”,也许Pytork实际上有它们,但不将它们视为“权重”。Keras将它们视为“权重”因为在保存/加载模型时会保存/加载它们,但它们在通常意义上肯定是“不可训练的”)

为什么积累这些统计数据很重要?因为当你使用你的模型进行预测(而不是训练)时,如果你的输入数据不是一个大批量的数据,或者如果你的输入数据与模型训练时的均值和标准差很大,你可能会得到错误的结果。我相信,在现实生活中,想要预测单个项目而不是一个大批量项目的情况并不少见

但是,如果您仍然想删除它们,您可以简单地从源代码复制代码,并删除与移动有关的所有内容

class BatchNormalization2(层):
"""
评论了所有关于移动统计的事情
"""
@interfaces.legacy_batchnorm_支持
定义初始化(自我,
轴=-1,
动量=0.99,
ε=1e-3,
中心=正确,
比例=真,
beta_初始值设定项='零',
gamma_初始值设定项='ones',
#移动\u均值\u初始值设定项='零',
#移动\u方差\u初始值设定项='ones',
beta_正则化器=无,
gamma_正则化器=无,
beta_约束=无,
伽马约束=无,
**kwargs):
超级(批处理规范化2,自)。\uuuuu初始化(**kwargs)
self.supports\u masking=True
self.axis=轴
自我动量=动量
self.epsilon=epsilon
self.center=中心
self.scale=scale
self.beta_初始值设定项=初始值设定项.get(beta_初始值设定项)
self.gamma_初始值设定项=初始值设定项.get(gamma_初始值设定项)
#self.moving\u mean\u initializer=initializers.get(moving\u mean\u initializer)
#self.moving_variance_initializer=(initializers.get(moving_variance_initializer))
self.beta\u正则化器=正则化器.get(beta\u正则化器)
self.gamma\u正则化器=正则化器.get(gamma\u正则化器)
self.beta\u constraint=constraints.get(beta\u constraint)
self.gamma_constraint=constraints.get(gamma_constraint)
def构建(自我,输入_形状):
dim=输入_形状[自身轴]
如果dim为无:
提升值错误('Axis'+str(self.Axis)+'of'
'输入张量应具有定义的维度'
'但该层接收到一个带有形状的输入'+
str(输入_形)+'.')
self.input\u spec=InputSpec(ndim=len(input\u shape),
轴={self.axis:dim})
形状=(尺寸,)
如果是自评量表:
self.gamma=self.add_权重(形状=形状,
name='gamma',
初始值设定项=self.gamma\u初始值设定项,
正则化器=自伽马正则化器,
约束=self.gamma_约束)
其他:
self.gamma=无
如果自我中心:
self.beta=self.add_重量(形状=形状,
name='beta',
初始值设定项=self.beta\u初始值设定项,
正则化器=self.beta_正则化器,
约束=self.beta_约束)
其他:
self.beta=无
#self.moving\u mean=self.add\u权重(
#形状=形状,
#name='moving''u意思是',
#初始值设定项=自移动\u平均值\u初始值设定项,
#可培训=错误)
#self.moving\u variance=self.add\u权重(
#形状=形状,
#name='moving_variance',
#初始值设定项=自移动\u方差\u初始值设定项,
#可培训=错误)
自建=真
def呼叫(自我、输入、培训=无):
输入形状=K.int形状(输入)
#准备广播形状。
ndim=len(输入_形)
缩小轴=列表(范围(透镜(输入形状)))
del reduction_轴[自身轴]
广播形状=[1]*len(输入形状)
广播_形[self.axis]=输入_形[self.axis]
#确定是否需要广播。
需要广播=(已排序(减少轴)!=列表(范围(ndim))[:-1])
#def normalize_推断():
#如果需要广播:
##在这种情况下,我们必须显式广播所有参数。
#广播移动平均值=K.重塑(自移动平均值,
#