代码之家  ›  专栏  ›  技术社区  ›  Jane Sully

如何将Keras Multiply()与tf结合使用。变量

  •  0
  • Jane Sully  · 技术社区  · 4 年前

    我如何繁殖 tf.keras.layers 具有 tf.Variable ?

    背景:我正在创建一个依赖于样本的卷积滤波器,它由一个通用滤波器组成 W 这是通过依赖样本的移位+缩放来转换的。因此,卷积原始滤波器 W 变成 aW + b 哪里 a 是依赖于样本的缩放和 b 是样本依赖的移位。这种方法的一个应用是训练一个自动编码器,其中样本相关性是标签,因此每个标签都会移动/缩放卷积滤波器。由于样本/标签相关的卷积,我使用 tf.nn.conv2d 它将实际的过滤器作为输入(而不仅仅是过滤器的数量/大小),并带有一个lambda层 tf.map_fn 为每个样本应用不同的“变换过滤器”(基于标签)。虽然细节有所不同,但这种依赖样本的卷积方法将在本文中讨论: 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。据我所知,这是变数。我该怎么解决这个问题?假设维度/形状广播工作正常,我想这样做(注意:输出仍然应该是与var相同的形状,只是沿着32个输出过滤器维度中的每个维度进行缩放)

    output = tf.keras.layers.Multiply()([var, scale]) 
    
    0 回复  |  直到 4 年前
        1
  •  1
  •   thushv89    4 年前

    它需要一些工作,需要一个自定义层。比如你 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)
    

    笔记 :请注意,我没有添加偏见。卷积层也需要偏置。但这是直截了当的。