Tensorflow 如何在不考虑方差的情况下去除Keras层的平均值,如Batchnormalization?

Tensorflow 如何在不考虑方差的情况下去除Keras层的平均值,如Batchnormalization?,tensorflow,keras,normalization,centering,batch-normalization,Tensorflow,Keras,Normalization,Centering,Batch Normalization,我想做BatchNormalization layer在Keras中所做的,移除平均值并存储移动平均值。不幸的是,这个函数也总是考虑方差,我不想使用它 我在考虑使用平均层和减法层,但它们不存储任何内容以供训练结束时使用。我的想法是,我的层删除并学习平均值,因此在测试中预测时,它减去一个常量值。我创建了一个居中层来实现这一点,从批量标准化复制。它使用动量移动当前移动平均值。它似乎可以工作,我可以用它保存和加载模型 从tensorflow.keras导入后端 从tensorflow.keras导入初

我想做BatchNormalization layer在Keras中所做的,移除平均值并存储移动平均值。不幸的是,这个函数也总是考虑方差,我不想使用它


我在考虑使用平均层和减法层,但它们不存储任何内容以供训练结束时使用。我的想法是,我的层删除并学习平均值,因此在测试中预测时,它减去一个常量值。

我创建了一个
居中
层来实现这一点,从
批量标准化
复制。它使用动量移动当前移动平均值。它似乎可以工作,我可以用它保存和加载模型

从tensorflow.keras导入后端
从tensorflow.keras导入初始值设定项
从tensorflow.keras导入图层
从tensorflow导入数学
从tensorflow.python.distribute导入分发\u策略\u上下文
从tensorflow.python.framework导入ops
从tensorflow.python.keras.utils导入tf_utils
从tensorflow.python.ops导入数组
从tensorflow.python.ops导入数学运算
从tensorflow.python.ops导入状态
从tensorflow.python.ops导入变量
类居中(层。层):
“”“以平均值为中心的数据层。”“”
定义初始(自,动量=0.01,**kwargs):
“”“LatentProjection的构造函数。”“”
如果“输入形状”不在kwargs中,而“输入尺寸”在kwargs中:
kwargs['input_shape']=(kwargs.pop('input_dim'),)
超级()
self.input\u spec=layers.InputSpec(最小ndim=2)
自我动量=动量
self.moving_mean=无
def构建(自我,输入_形状):
“”“创建内部变量。”“”
断言len(输入_形状)>=2
输入尺寸=输入形状[-1]
self.moving\u mean=self.add\u权重(
name='moving''u意思是',
形状=(输入尺寸,),
初始值设定项=初始值设定项.0,
同步=variables.VariableSynchronization.ON_READ,
可训练=错误,
聚合=变量。变量聚合。平均值,
实验性(自动广播=错误)
self.input\u spec=layers.InputSpec(min\u ndim=2,axes={-1:input\u dim})
自建=真
def_获取_培训_值(自我,培训=无):
“”“从normalization.py复制。”“”
如果没有培训:
培训=后端。学习阶段()
如果isinstance(培训,int):
培训=bool(培训)
如果不能自我培训:
#当图层不可训练时,它将覆盖该值
#从模型中传递。
训练=错误
返回训练
def_支持_零尺寸_输入(自身):
“”“从normalization.py复制。”“”
返回分发策略上下文。具有策略()和getattr(
分发策略上下文。获取策略()扩展,
“实验性启用下一步作为可选”,False)
定义分配移动平均值(自身、变量、值、动量、输入大小):
“”“从normalization.py复制。”“”
使用backend.name_scope('AssignMovingAvg')作为作用域:
使用ops.colocate_和(变量):
衰变=运算。转换为张量(1.0-动量,name='衰变')
如果decay.dtype!=variable.dtype.base\u dtype:
detacy=math_ops.cast(detacy,variable.dtype.base_dtype)
更新_delta=(变量-
math_ops.cast(value,variable.dtype))*衰减
如果输入大小不是无:
更新_delta=数组_ops.where(
输入大小>0,更新增量,
后端。类零(更新增量))
返回状态分配(变量,更新增量,名称=范围)
def呼叫(自我、输入、培训=无,**kwargs):
“”“应用于输入层时,为每个小批次调用。”“”
培训=自我。获得培训价值(培训)
训练值=tf实用值。恒定值(训练)
如果训练值=False:
平均值=自移动平均值
其他:
平均值=数学。减少平均值(输入,轴=0)
#以下代码从normalization.py复制来更新移动平均值
如果self.\u支持\u零\u大小\u输入():
#Keras假设批次维度是产品的第一个维度
#批处理规范化。
输入\批处理\大小=数组\运算形状(输入)[0]
其他:
输入\批次\大小=无
def mean_update():
“”“使用复制的代码执行移动平均值更新。”“”
自我分配移动平均(
self.moving_平均值,平均值,self.mounce,输入_批量大小)
自我添加更新(平均更新)
#中心输入
返回输入-平均值
def get_配置(自身):
“”“此层的内部配置。”“”
配置={
“动力”:自我动力,
}
base_config=super().get_config()
return dict(list(base_config.items())+list(config.items())