如何使用 tf.keras 编写自定义标准层
How to write a custom stdandardization layer with tf.keras
目前我正在使用 tensorflow 和 keras 构建我的第一个神经网络 API。
我想写一个层来标准化输入,因为在预处理中这样做可能会导致在训练后使用模型时出错。
因此我想将我的训练数据集传递给该层的初始化函数并计算均值和标准差。
问题是我还想在训练后保存和加载模型。但是如果我调用 load_model(modelname) 我会得到一个错误,因为 init 函数需要训练数据作为参数。此外,我不确定将平均值和标准差指定为 tf.Variable 是否正确,或者是否有更好的方法,以便在使用 load_model/load_weights.[=12= 时加载这些值]
我很高兴得到每一个答案。
下面的代码代表了这种层的基本思想。
class stdLayer(tf.keras.layers.Layer):
def __init__(self, train_x, trainable=False,**kwargs):
super(stdLayer, self).__init__(trainable=trainable,**kwargs)
means=np.mean(train_x,axis=0)
stds=np.std(train_x,axis=0)
self.means = tf.Variable(means,
dtype=tf.float32,
name="means",
trainable=False)
self.stds = tf.Variable(stds,
dtype=tf.float32,
name="stds",
trainable=False)
def call(self, input):
input_st = (input-self.means)/self.stds
return input_st
也许您可以在模型的开头添加一个 BatchNormalization
层。
不过,在所有情况下,您都需要生产数据的格式与训练数据的格式相同。
或者,不传递训练数据,只传递 means
和 stds
。
class StdLayer(tf.keras.layers.Layer):
def __init__(self, means, stds, trainable=False,**kwargs):
...
self.means_init = means
self.stds_init = stds
...
def build(self, input_shape):
self.means = self.add_weight(name='means',
shape=self.means_init.shape,
initializer='zeros',
trainable=True)
#if you put false here, they will never be trainable
self.stds = self.add_weight(name='stds',
shape=self.stds_init.shape,
initializer='ones',
trainable=True)
#if you put false here, they will never be trainable
keras.backend.set_value(self.means, self.means_init)
keras.backend.set_value(self.stds, self.stds)
self.built = True
def call(self, inputs):
...
def compute_output_shape(self, input_shape):
...
def get_config(self):
config = {
'means_init': self.means_init,
'stds_init': self.stds_init,
}
base_config = super(StdLayer, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
老实说,我不确定是否可以将 numpy 数组传递给 config
。
您也许可以使用 __init__(self, means=None, stds=None, ...
,并在 build
中放置一个 if
作为 set_values
。找到另一种方法来计算 add_weight
中的形状,您可以摆脱 config
变量。
目前我正在使用 tensorflow 和 keras 构建我的第一个神经网络 API。 我想写一个层来标准化输入,因为在预处理中这样做可能会导致在训练后使用模型时出错。 因此我想将我的训练数据集传递给该层的初始化函数并计算均值和标准差。
问题是我还想在训练后保存和加载模型。但是如果我调用 load_model(modelname) 我会得到一个错误,因为 init 函数需要训练数据作为参数。此外,我不确定将平均值和标准差指定为 tf.Variable 是否正确,或者是否有更好的方法,以便在使用 load_model/load_weights.[=12= 时加载这些值]
我很高兴得到每一个答案。
下面的代码代表了这种层的基本思想。
class stdLayer(tf.keras.layers.Layer):
def __init__(self, train_x, trainable=False,**kwargs):
super(stdLayer, self).__init__(trainable=trainable,**kwargs)
means=np.mean(train_x,axis=0)
stds=np.std(train_x,axis=0)
self.means = tf.Variable(means,
dtype=tf.float32,
name="means",
trainable=False)
self.stds = tf.Variable(stds,
dtype=tf.float32,
name="stds",
trainable=False)
def call(self, input):
input_st = (input-self.means)/self.stds
return input_st
也许您可以在模型的开头添加一个 BatchNormalization
层。
不过,在所有情况下,您都需要生产数据的格式与训练数据的格式相同。
或者,不传递训练数据,只传递 means
和 stds
。
class StdLayer(tf.keras.layers.Layer):
def __init__(self, means, stds, trainable=False,**kwargs):
...
self.means_init = means
self.stds_init = stds
...
def build(self, input_shape):
self.means = self.add_weight(name='means',
shape=self.means_init.shape,
initializer='zeros',
trainable=True)
#if you put false here, they will never be trainable
self.stds = self.add_weight(name='stds',
shape=self.stds_init.shape,
initializer='ones',
trainable=True)
#if you put false here, they will never be trainable
keras.backend.set_value(self.means, self.means_init)
keras.backend.set_value(self.stds, self.stds)
self.built = True
def call(self, inputs):
...
def compute_output_shape(self, input_shape):
...
def get_config(self):
config = {
'means_init': self.means_init,
'stds_init': self.stds_init,
}
base_config = super(StdLayer, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
老实说,我不确定是否可以将 numpy 数组传递给 config
。
您也许可以使用 __init__(self, means=None, stds=None, ...
,并在 build
中放置一个 if
作为 set_values
。找到另一种方法来计算 add_weight
中的形状,您可以摆脱 config
变量。