Создание подкласса слоя Keras: следующие переменные использовались при вызове слоя Lambda, но отсутствуют в его отслеживаемых объектах.

Я создаю собственный сверточный слой, подклассом слоя Keras. Я сделал это с предыдущей версией Tensorflow и не получил предупреждений:

import tensorflow as tf


class MyCustomLayer(tf.Module):
    def __init__(self, in_channels,
                 filters,
                 kernel_size,
                 padding,
                 strides,
                 activation,
                 kernel_initializer,
                 bias_initializer,
                 use_bias):
        super(MyCustomLayer, self).__init__()
        self.filters = filters
        self.kernel_size = kernel_size
        self.activation = activation
        self.padding = padding
        self.kernel_initializer = kernel_initializer
        self.bias_initializer = bias_initializer
        self.strides = strides
        self.use_bias = use_bias
        self.in_channels = in_channels

        self.w = tf.Variable(
            initial_value=self.kernel_initializer(shape=(*self.kernel_size,
                                                         in_channels,
                                                         self.filters),
                                 dtype='float32'), trainable=True)
        if self.use_bias:
            self.b = tf.Variable(
                initial_value=self.bias_initializer(shape=(self.filters,),
                                                    dtype='float32'),
                trainable=True)

    def __call__(self, inputs, training=None):
        x =  tf.nn.conv2d(inputs,
                          filters=self.w,
                          strides=self.strides,
                          padding=self.padding)
        if self.use_bias:
            x = tf.add(x, self.b)
        x = self.activation(x)
        return x


x = tf.keras.Input(shape=(28, 28, 3))
y = MyCustomLayer(
            in_channels=3,
            filters=16,
            kernel_size=(3, 3),
            strides=(1, 1),
            activation=tf.nn.relu,
            padding='VALID',
            kernel_initializer=tf.initializers.GlorotUniform(),
            bias_initializer=tf.initializers.Zeros(),
            use_bias=True)(x)
model = tf.keras.Model(inputs=x, outputs=y)

Я получаю это предупреждение с tf.__version__ == 2.4.1:

ВНИМАНИЕ:tensorflow: следующие переменные использовались при вызове слоя Lambda (tf.compat.v1.nn.conv2d_12), но отсутствуют в его отслеживаемых объектах: ‹tf.Variable 'Variable:0' shape=(3, 3, 3, 16) dtype=float32› Возможно, это задуманное поведение, но, скорее, это упущение. Это убедительный признак того, что этот уровень следует сформулировать как слой подкласса, а не как слой Lambda.

ВНИМАНИЕ:tensorflow: следующие переменные использовались при вызове слоя Lambda (tf.math.add_2), но отсутствуют в его отслеживаемых объектах: ‹tf.Variable 'Variable:0' shape=(16,) dtype=float32> возможно, это преднамеренное поведение, но, скорее всего, это упущение. Это убедительный признак того, что этот уровень следует сформулировать как слой подкласса, а не как слой Lambda.

Что это значит? Я использую слой с подклассом.


person Nicolas Gervais    schedule 30.03.2021    source источник
comment
Вы случайно не решили эту проблему?   -  person Rahil Kadakia    schedule 04.06.2021


Ответы (1)


Вот некоторая подсказка. Я нашел блог, где это обсуждалось . Здесь утверждается

tf.keras.Lambda: обратите внимание, что если в слое, созданном этим методом, задействованы переменные, переменная не будет автоматически добавлена ​​в набор переменных для расчета градиента. Поэтому, если в определяемом пользователем слое есть параметры для обучения, рекомендуется настроить слой модели на основе базового класса.

Они показали

weights = tf.Variable(tf.random.normal((4, 2)), name='w')
bias = tf.ones((1, 2), name='b')
print(bias)
x_input = tf.range(12.).numpy().reshape(-1, 4)

# lambda custom layer
mylayer1 = tf.keras.layers.Lambda(lambda x: tf.add(tf.matmul(x, weights),
                                                           bias), name='lambda1')
mylayer1(x_input)

tf.Tensor([[1. 1.]], shape=(1, 2), dtype=float32)
WARNING:tensorflow:
The following Variables were used a Lambda layer's call (lambda1), but
are not present in its tracked objects:
  <tf.Variable 'w:0' shape=(4, 2) dtype=float32, numpy=
array([[ 2.54332  ,  1.5078725],
       [ 0.5291851, -1.1049112],
       [ 1.475109 , -1.6525942],
       [ 1.593746 , -0.4049823]], dtype=float32)>
It is possible that this is intended behavior, but it is more likely
an omission. This is a strong indication that this layer should be
formulated as a subclassed Layer rather than a Lambda layer.
<tf.Tensor: shape=(3, 2), dtype=float32, numpy=
array([[  9.260641 ,  -4.6250463],
       [ 33.82608  , -11.243508 ],
       [ 58.391525 , -17.861969 ]], dtype=float32)>

Они также показали способ обойти предупреждение. Но я не уверен (пока), что можно сделать, чтобы обойти в вашем случае. Быстрый обзор исходного кода tf.compat.v1.nn.conv2d, приводит к лямбда выражение, которое может быть причиной.

 def build_op(num_spatial_dims, padding):
    return lambda inp, _: op(inp, num_spatial_dims, padding)
person M.Innat    schedule 30.03.2021