如何将 Keras Multiply() 与 tf.Variable 一起使用?
How to use Keras Multiply() with tf.Variable?
如何将 tf.keras.layers
与 tf.Variable
相乘?
上下文:我正在创建一个依赖于样本的卷积滤波器,它由一个通用滤波器 W
组成,该滤波器通过依赖于样本的移位 + 缩放进行转换。因此,卷积原始滤波器 W
被转换为 aW + b
,其中 a
是样本相关缩放,b
是样本相关移位。它的一个应用是训练一个自动编码器,其中样本相关性是标签,因此每个标签 shifts/scales 卷积过滤器。由于 sample/label 依赖卷积,我使用 tf.nn.conv2d
将实际过滤器作为输入(而不是仅 number/size 过滤器)和一个带有 tf.map_fn
的 lambda 层为每个样本应用不同的“转换过滤器”(基于标签)。虽然细节不同,但这种依赖于样本的卷积方法在这个 post 中讨论:.
这是我的想法:
input_img = keras.Input(shape=(28, 28, 1))
label = keras.Input(shape=(10,)) # number of classes
num_filters = 32
shift = layers.Dense(num_filters, activation=None, name='shift')(label) # (32,)
scale = layers.Dense(num_filters, activation=None, name='scale')(label) # (32,)
# filter is of shape (filter_h, filter_w, input channels, output filters)
filter = tf.Variable(tf.ones((3,3,input_img.shape[-1],num_filters)))
# TODO: need to shift and scale -> shift*(filter) + scale along each output filter dimension (32 filter dimensions)
我不确定如何实现 TODO
部分。我正在考虑 tf.keras.layers.Multiply()
用于缩放,tf.keras.layers.Add()
用于移动,但据我所知,它们似乎不适用于 tf.Variable。我该如何解决这个问题?假设 dimensions/shape 广播成功了,我想做这样的事情(注意:输出应该仍然是与 var 相同的形状,并且只是沿着 32 个输出过滤器维度中的每一个维度缩放)
output = tf.keras.layers.Multiply()([var, scale])
它需要一些工作并且需要一个自定义层。例如你
class ConvNorm(layers.Layer):
def __init__(self, height, width, n_filters):
super(ConvNorm, self).__init__()
self.height = height
self.width = width
self.n_filters = n_filters
def build(self, input_shape):
self.filter = self.add_weight(shape=(self.height, self.width, input_shape[-1], self.n_filters),
initializer='glorot_uniform',
trainable=True)
# TODO: Add bias too
def call(self, x, scale, shift):
shift_reshaped = tf.expand_dims(tf.expand_dims(shift,1),1)
scale_reshaped = tf.expand_dims(tf.expand_dims(scale,1),1)
norm_conv_out = tf.nn.conv2d(x, self.filter*scale + shift, strides=(1,1,1,1), padding='SAME')
return norm_conv_out
使用图层
import tensorflow as tf
import tensorflow.keras.layers as layers
input_img = layers.Input(shape=(28, 28, 1))
label = layers.Input(shape=(10,)) # number of classes
num_filters = 32
shift = layers.Dense(num_filters, activation=None, name='shift')(label) # (32,)
scale = layers.Dense(num_filters, activation=None, name='scale')(label) # (32,)
conv_norm_out = ConvNorm(3,3,32)(input_img, scale, shift)
print(norm_conv_out.shape)
注意:请注意,我没有添加偏见。卷积层也需要偏置。但这很简单。
如何将 tf.keras.layers
与 tf.Variable
相乘?
上下文:我正在创建一个依赖于样本的卷积滤波器,它由一个通用滤波器 W
组成,该滤波器通过依赖于样本的移位 + 缩放进行转换。因此,卷积原始滤波器 W
被转换为 aW + b
,其中 a
是样本相关缩放,b
是样本相关移位。它的一个应用是训练一个自动编码器,其中样本相关性是标签,因此每个标签 shifts/scales 卷积过滤器。由于 sample/label 依赖卷积,我使用 tf.nn.conv2d
将实际过滤器作为输入(而不是仅 number/size 过滤器)和一个带有 tf.map_fn
的 lambda 层为每个样本应用不同的“转换过滤器”(基于标签)。虽然细节不同,但这种依赖于样本的卷积方法在这个 post 中讨论:
这是我的想法:
input_img = keras.Input(shape=(28, 28, 1))
label = keras.Input(shape=(10,)) # number of classes
num_filters = 32
shift = layers.Dense(num_filters, activation=None, name='shift')(label) # (32,)
scale = layers.Dense(num_filters, activation=None, name='scale')(label) # (32,)
# filter is of shape (filter_h, filter_w, input channels, output filters)
filter = tf.Variable(tf.ones((3,3,input_img.shape[-1],num_filters)))
# TODO: need to shift and scale -> shift*(filter) + scale along each output filter dimension (32 filter dimensions)
我不确定如何实现 TODO
部分。我正在考虑 tf.keras.layers.Multiply()
用于缩放,tf.keras.layers.Add()
用于移动,但据我所知,它们似乎不适用于 tf.Variable。我该如何解决这个问题?假设 dimensions/shape 广播成功了,我想做这样的事情(注意:输出应该仍然是与 var 相同的形状,并且只是沿着 32 个输出过滤器维度中的每一个维度缩放)
output = tf.keras.layers.Multiply()([var, scale])
它需要一些工作并且需要一个自定义层。例如你
class ConvNorm(layers.Layer):
def __init__(self, height, width, n_filters):
super(ConvNorm, self).__init__()
self.height = height
self.width = width
self.n_filters = n_filters
def build(self, input_shape):
self.filter = self.add_weight(shape=(self.height, self.width, input_shape[-1], self.n_filters),
initializer='glorot_uniform',
trainable=True)
# TODO: Add bias too
def call(self, x, scale, shift):
shift_reshaped = tf.expand_dims(tf.expand_dims(shift,1),1)
scale_reshaped = tf.expand_dims(tf.expand_dims(scale,1),1)
norm_conv_out = tf.nn.conv2d(x, self.filter*scale + shift, strides=(1,1,1,1), padding='SAME')
return norm_conv_out
使用图层
import tensorflow as tf
import tensorflow.keras.layers as layers
input_img = layers.Input(shape=(28, 28, 1))
label = layers.Input(shape=(10,)) # number of classes
num_filters = 32
shift = layers.Dense(num_filters, activation=None, name='shift')(label) # (32,)
scale = layers.Dense(num_filters, activation=None, name='scale')(label) # (32,)
conv_norm_out = ConvNorm(3,3,32)(input_img, scale, shift)
print(norm_conv_out.shape)
注意:请注意,我没有添加偏见。卷积层也需要偏置。但这很简单。