【问题标题】:How to use Keras Multiply() with tf.Variable?如何将 Keras Multiply() 与 tf.Variable 一起使用?
【发布时间】:2021-01-17 17:28:15
【问题描述】:

如何将tf.keras.layerstf.Variable 相乘?

上下文:我正在创建一个依赖于样本的卷积过滤器,它由一个通用过滤器W 组成,该过滤器通过依赖于样本的移位+缩放进行转换。因此,卷积原始滤波器W 转换为aW + b,其中a 是与样本相关的缩放,b 是与样本相关的移位。一个应用是训练一个自动编码器,其中样本依赖项是标签,因此每个标签都会移动/缩放卷积滤波器。由于与样本/标签相关的卷积,我使用tf.nn.conv2d 将实际过滤器作为输入(而不仅仅是过滤器的数量/大小)和一个带有tf.map_fn 的lambda 层以应用不同的“变换过滤器”(基于标签)为每个样本。虽然细节有所不同,但这种依赖于样本的卷积方法在这篇博文中进行了讨论:Tensorflow: Convolutions with different filter for each sample in the mini-batch

这是我的想法:

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。我该如何解决这个问题?假设尺寸/形状广播工作,我想做这样的事情(注意:输出应该仍然与 var 相同的形状,只是沿着 32 个输出过滤器维度中的每一个进行缩放)

output = tf.keras.layers.Multiply()([var, scale]) 

【问题讨论】:

  • 你能解释一下你的var的形状吗?
  • 对不起,不够清晰。我将var 更改为filter 以表明这是卷积滤波器(在移位/缩放之前)。它的形状为 (filter_height, filter_width, input channels, output filters),在本例中为 (3,3,1,32)。

标签: tensorflow keras conv-neural-network keras-layer map-function


【解决方案1】:

它需要一些工作并且需要一个自定义层。比如你cannot use tf.Variable with tf.keras.Lambda

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)

注意:请注意,我没有添加偏见。卷积层也需要偏置。但这很简单。

【讨论】:

  • 非常感谢您的回复。我绝对无法自己实现自定义层,因此我感谢您的帮助。我有一些后续问题可能很明显。 1) scale_reshapedshift_reshaped 是否意外包含在 call() 中两次? 2)我不认为scale_reshapedshift_reshaped用于修改过滤器,但我认为应该?这是有意的/我的理解正确吗? 3) 你为什么要为tf.nn.conv2d*x[2]+x[3]?谢谢!
  • @JaneSully 你说的一切都是正确的。我想我太粗心了。修复了问题
猜你喜欢
  • 2023-02-04
  • 1970-01-01
  • 2018-12-30
  • 2020-09-28
  • 1970-01-01
  • 1970-01-01
  • 2020-04-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多