通过 tensorflow 将归一化重现到 keras
Reproduce normalization by tensorflow to keras
实际上我正在尝试在 keras 上重现一个 tensorflow 模型,我对这个话题真的很陌生。
我想重现这些行
embedding = tf.layers.conv2d(conv6, 128, (16, 16), padding='VALID', name='embedding')
embedding = tf.reshape(embedding, (-1, 128))
embedding = embedding - tf.reduce_min(embedding, keepdims =True)
z_n = embedding/tf.reduce_max(embedding, keepdims =True)
我的实际代码是:
def conv_conv_pool(n_filters,
name,
pool=True,
activation=tf.nn.relu, padding='same', filters=(3,3)):
"""{Conv -> BN -> RELU}x2 -> {Pool, optional}
Args:
input_ (4-D Tensor): (batch_size, H, W, C)
n_filters (list): number of filters [int, int]
training (1-D Tensor): Boolean Tensor
name (str): name postfix
pool (bool): If True, MaxPool2D
activation: Activaion functions
Returns:
net: output of the Convolution operations
pool (optional): output of the max pooling operations
"""
net = Sequential()
for i, F in enumerate(n_filters):
conv = Conv2D(
filters = F,
kernel_size = (3,3),
padding = 'same',
)
net.add(conv)
batch_norm = BatchNormalization()
net.add(batch_norm)
net.add(Activation('relu'))
if pool is False:
return net
pool = Conv2D(
filters = F,
kernel_size = (3,3),
strides = (2,2),
padding = 'same',
)
net.add(pool)
batch_norm = BatchNormalization()
net.add(batch_norm)
net.add(Activation('relu'))
return net
def model_keras():
model = Sequential()
model.add(conv_conv_pool(n_filters = [8, 8], name="1"))
model.add(conv_conv_pool([32, 32], name="2"))
model.add(conv_conv_pool([32, 32], name="3"))
model.add(conv_conv_pool([64, 64], name="4"))
model.add(conv_conv_pool([64, 64], name="5"))
model.add(conv_conv_pool([128, 128], name="6", pool=False))
return model
归一化应该在第 6 层之后。
我在考虑使用 lambda 层,这对吗?是的话应该怎么写?
我相信您想切换到使用 keras 作为 API 的 tensorflow 2。你需要 install/upgrade 到 tensorflow 2,然后你可以试试这个:
import tensorflow as tf
embedding = tf.keras.layers.conv2d(conv6, 128, (16, 16), padding='VALID',
name='embedding')
embedding = tf.keras.layers.reshape(embedding, (-1, 128))
embedding = embedding - tf.math.reduce_min(embedding, keepdims =True)
z_n = embedding/tf.math.reduce_max(embedding, keepdims =True)
如果你想使用 keras 层 api 你可以创建一个自定义层,你可以在这里找到如何做的文档
https://www.tensorflow.org/guide/keras/custom_layers_and_models,
你应该以这样的方式结束:
class NormalizationLayer(layers.Layer):
def __init__(self, filters=128):
super(NormalizationLayer, self).__init__()
self.filters = filters
def call(self, inputs):
embedding = tf.keras.layers.conv2d(inputs, self.filters, (16, 16), padding='VALID',
name='embedding')
embedding = tf.keras.layers.reshape(embedding, (-1, self.filters))
embedding = embedding - tf.math.reduce_min(embedding, keepdims =True)
z_n = embedding/tf.math.reduce_max(embedding, keepdims =True)
return zn
我使用您在 Lambda 层中引入的规范化。我还做了一个更正(最小值和最大值是在同一个输入上计算的,而不是一个在输入上计算,另一个在转换上计算),但你也可以改变它。 norm_original
使用在所有通道上计算的最小值和最大值对 4D 输入进行归一化,并尝试 return 具有固定数量特征的 2D 输出这将产生错误,因为您正在修改批量维度
def norm_original(inp):
embedding = tf.reshape(inp, (-1, inp.shape[-1]))
embedding = embedding - tf.reduce_min(inp)
embedding = embedding / tf.reduce_max(inp)
return embedding
inp = Input((28,28,3))
x = Conv2D(128, 3, padding='same')(inp)
x = Lambda(norm_original)(x)
m = Model(inp, x)
m.compile('adam', 'mse')
m.summary()
X = np.random.uniform(0,1, (10,28,28,3))
y = np.random.uniform(0,1, (10,128))
m.fit(X,y, epochs=3) # error
为了避免这个错误,我提出了两种可能性。我也做了修改,按通道操作归一化(我保留它更合适)但你也可以修改它。
1) 您可以使用 min/max 规范化 4D 输入,然后将输出展平,将所有内容放在最后一个维度上。此解决方案不会交替批处理 dim
def norm(inp):
## this function operate normalization by channels
embedding = inp - tf.reduce_min(inp, keepdims=True, axis=[0,1,2])
embedding = embedding / tf.reduce_max(inp, keepdims=True, axis=[0,1,2])
return embedding
inp = Input((28,28,3))
x = Conv2D(128, 3, padding='same')(inp)
x = Lambda(norm)(x)
x = Flatten()(x)
x = Dense(128, activation='relu')(x)
m = Model(inp, x)
m.compile('adam', 'mse')
X = np.random.uniform(0,1, (10,28,28,3))
y = np.random.uniform(0,1, (10,128))
m.fit(X,y, epochs=3)
2) 您可以使用 GlobalPooling 层来减少 4D 维度并重新生成 2D 形状,保留特征维度
inp = Input((28,28,3))
x = Conv2D(128, 3, padding='same')(inp)
x = Lambda(norm)(x)
x = GlobalMaxPool2D()(x) # u can also use GlobalAveragePooling2D
m = Model(inp, x)
m.compile('adam', 'mse')
X = np.random.uniform(0,1, (10,28,28,3))
y = np.random.uniform(0,1, (10,128))
m.fit(X,y, epochs=3)
实际上我正在尝试在 keras 上重现一个 tensorflow 模型,我对这个话题真的很陌生。 我想重现这些行
embedding = tf.layers.conv2d(conv6, 128, (16, 16), padding='VALID', name='embedding')
embedding = tf.reshape(embedding, (-1, 128))
embedding = embedding - tf.reduce_min(embedding, keepdims =True)
z_n = embedding/tf.reduce_max(embedding, keepdims =True)
我的实际代码是:
def conv_conv_pool(n_filters,
name,
pool=True,
activation=tf.nn.relu, padding='same', filters=(3,3)):
"""{Conv -> BN -> RELU}x2 -> {Pool, optional}
Args:
input_ (4-D Tensor): (batch_size, H, W, C)
n_filters (list): number of filters [int, int]
training (1-D Tensor): Boolean Tensor
name (str): name postfix
pool (bool): If True, MaxPool2D
activation: Activaion functions
Returns:
net: output of the Convolution operations
pool (optional): output of the max pooling operations
"""
net = Sequential()
for i, F in enumerate(n_filters):
conv = Conv2D(
filters = F,
kernel_size = (3,3),
padding = 'same',
)
net.add(conv)
batch_norm = BatchNormalization()
net.add(batch_norm)
net.add(Activation('relu'))
if pool is False:
return net
pool = Conv2D(
filters = F,
kernel_size = (3,3),
strides = (2,2),
padding = 'same',
)
net.add(pool)
batch_norm = BatchNormalization()
net.add(batch_norm)
net.add(Activation('relu'))
return net
def model_keras():
model = Sequential()
model.add(conv_conv_pool(n_filters = [8, 8], name="1"))
model.add(conv_conv_pool([32, 32], name="2"))
model.add(conv_conv_pool([32, 32], name="3"))
model.add(conv_conv_pool([64, 64], name="4"))
model.add(conv_conv_pool([64, 64], name="5"))
model.add(conv_conv_pool([128, 128], name="6", pool=False))
return model
归一化应该在第 6 层之后。
我在考虑使用 lambda 层,这对吗?是的话应该怎么写?
我相信您想切换到使用 keras 作为 API 的 tensorflow 2。你需要 install/upgrade 到 tensorflow 2,然后你可以试试这个:
import tensorflow as tf
embedding = tf.keras.layers.conv2d(conv6, 128, (16, 16), padding='VALID',
name='embedding')
embedding = tf.keras.layers.reshape(embedding, (-1, 128))
embedding = embedding - tf.math.reduce_min(embedding, keepdims =True)
z_n = embedding/tf.math.reduce_max(embedding, keepdims =True)
如果你想使用 keras 层 api 你可以创建一个自定义层,你可以在这里找到如何做的文档 https://www.tensorflow.org/guide/keras/custom_layers_and_models, 你应该以这样的方式结束:
class NormalizationLayer(layers.Layer):
def __init__(self, filters=128):
super(NormalizationLayer, self).__init__()
self.filters = filters
def call(self, inputs):
embedding = tf.keras.layers.conv2d(inputs, self.filters, (16, 16), padding='VALID',
name='embedding')
embedding = tf.keras.layers.reshape(embedding, (-1, self.filters))
embedding = embedding - tf.math.reduce_min(embedding, keepdims =True)
z_n = embedding/tf.math.reduce_max(embedding, keepdims =True)
return zn
我使用您在 Lambda 层中引入的规范化。我还做了一个更正(最小值和最大值是在同一个输入上计算的,而不是一个在输入上计算,另一个在转换上计算),但你也可以改变它。 norm_original
使用在所有通道上计算的最小值和最大值对 4D 输入进行归一化,并尝试 return 具有固定数量特征的 2D 输出这将产生错误,因为您正在修改批量维度
def norm_original(inp):
embedding = tf.reshape(inp, (-1, inp.shape[-1]))
embedding = embedding - tf.reduce_min(inp)
embedding = embedding / tf.reduce_max(inp)
return embedding
inp = Input((28,28,3))
x = Conv2D(128, 3, padding='same')(inp)
x = Lambda(norm_original)(x)
m = Model(inp, x)
m.compile('adam', 'mse')
m.summary()
X = np.random.uniform(0,1, (10,28,28,3))
y = np.random.uniform(0,1, (10,128))
m.fit(X,y, epochs=3) # error
为了避免这个错误,我提出了两种可能性。我也做了修改,按通道操作归一化(我保留它更合适)但你也可以修改它。
1) 您可以使用 min/max 规范化 4D 输入,然后将输出展平,将所有内容放在最后一个维度上。此解决方案不会交替批处理 dim
def norm(inp):
## this function operate normalization by channels
embedding = inp - tf.reduce_min(inp, keepdims=True, axis=[0,1,2])
embedding = embedding / tf.reduce_max(inp, keepdims=True, axis=[0,1,2])
return embedding
inp = Input((28,28,3))
x = Conv2D(128, 3, padding='same')(inp)
x = Lambda(norm)(x)
x = Flatten()(x)
x = Dense(128, activation='relu')(x)
m = Model(inp, x)
m.compile('adam', 'mse')
X = np.random.uniform(0,1, (10,28,28,3))
y = np.random.uniform(0,1, (10,128))
m.fit(X,y, epochs=3)
2) 您可以使用 GlobalPooling 层来减少 4D 维度并重新生成 2D 形状,保留特征维度
inp = Input((28,28,3))
x = Conv2D(128, 3, padding='same')(inp)
x = Lambda(norm)(x)
x = GlobalMaxPool2D()(x) # u can also use GlobalAveragePooling2D
m = Model(inp, x)
m.compile('adam', 'mse')
X = np.random.uniform(0,1, (10,28,28,3))
y = np.random.uniform(0,1, (10,128))
m.fit(X,y, epochs=3)