Home > Mobile >  Tensorflow 2.8.0 - Custom layer doesn't work out with tf.map_fn(tf.range,...)
Tensorflow 2.8.0 - Custom layer doesn't work out with tf.map_fn(tf.range,...)

Time:03-10

Dear stackoverflow community,

I am currently trying to create a custom layer that transforms every value of an input with integers into a vector with length "omega". Currently I combine the tensorflow functions tf.map_fn with the function tf.range to create a ragged tensor and fill that tensor up with zeros afterwards.

The Custom layer is defined as follows:

class ReshapeLayer(Layer):

    def __init__(self, omega):
        super(ReshapeLayer, self).__init__()
        # length of outputvector
        self.omega = omega
        
    def call(self, inputs, training=False):
        inputs = tf.cast(inputs, 'int32') #list of positive integer values
        print(inputs.shape) #(None, 1)
        output = tf.map_fn(tf.range, inputs, fn_output_signature=tf.RaggedTensorSpec(shape=[None])) #ERROR MESSAGE
        output = output.to_tensor(0,shape=[None,1,self.omega])
        return output

The error message I get is the following:

ValueError: Exception encountered when calling layer "reshape_layer" (type ReshapeLayer).

in user code:

    File "C:\Users\User\AppData\Local\Temp\ipykernel_13904\1349166236.py", line 13, in call  *
        output = tf.map_fn(tf.range, inputs, fn_output_signature=tf.RaggedTensorSpec(shape=[None])) #ERROR MESSAGE

    ValueError: Shape must be rank 0 but is rank 1
         for 'limit' for '{{node reshape_layer/map/while/range}} = Range[Tidx=DT_INT32](reshape_layer/map/while/range/start, reshape_layer/map/while/TensorArrayV2Read/TensorListGetItem, reshape_layer/map/while/range/delta)' with input shapes: [], [1], [].


Call arguments received:
  • inputs=tf.Tensor(shape=(None, 1), dtype=float32)
  • training=False

What I have tried was the following:

-) I tried to change inputs -> inputs[:,1], but this only changes the error message to

ValueError: Exception encountered when calling layer "reshape_layer_3" (type ReshapeLayer).

in user code:

    File "C:\Users\User\AppData\Local\Temp\ipykernel_13904\3917026906.py", line 13, in call  *
        output = tf.map_fn(tf.range, inputs[:,1], fn_output_signature=tf.RaggedTensorSpec(shape=[None])) #ERROR MESSAGE

    ValueError: slice index 1 of dimension 1 out of bounds. for '{{node reshape_layer_3/strided_slice}} = StridedSlice[Index=DT_INT32, T=DT_INT32, begin_mask=1, ellipsis_mask=0, end_mask=1, new_axis_mask=0, shrink_axis_mask=2](reshape_layer_3/Cast, reshape_layer_3/strided_slice/stack, reshape_layer_3/strided_slice/stack_1, reshape_layer_3/strided_slice/stack_2)' with input shapes: [?,1], [2], [2], [2] and with computed input tensors: input[1] = <0 1>, input[2] = <0 2>, input[3] = <1 1>.


Call arguments received:
  • inputs=tf.Tensor(shape=(None, 1), dtype=float32)
  • training=False


Example:

The input should be of the form (shape=[None,1]): Example:

omega = 10
input:
 x = [[5],[2],[3],[6]]
output:
y = [[0,1,2,3,4,0,0,0,0,0],
[0,1,0,0,0,0,0,0,0,0],
[0,1,2,0,0,0,0,0,0,0],
[0,1,2,3,4,5,0,0,0,0]]

Does anyone know a solution to this problem?

CodePudding user response:

Try using tf.while_loop and tf.tensor_scatter_nd_update:

import tensorflow as tf

class ReshapeLayer(tf.keras.layers.Layer):
  def __init__(self, omega):
    super(ReshapeLayer, self).__init__()
    # length of outputvector
    self.omega = omega
      
  def call(self, inputs, training=False):
    def body(i, x, zeros):
      r = tf.range(x[i][0], dtype=tf.int32)
      repeats = tf.repeat([i], tf.shape(r)[0])
      zeros = tf.tensor_scatter_nd_update(zeros, tf.stack([repeats, r], axis=1), r)
      return tf.add(i, 1), x, zeros

    zeros = tf.zeros((tf.shape(inputs)[0], self.omega), dtype=tf.int32)
    i = tf.constant(0)
    condition = lambda i, inputs, zeros: tf.less(i, tf.shape(inputs)[0])
    _, _, output = tf.while_loop(condition, body, loop_vars=[i, inputs, zeros])

    return output

omega = 10
x = tf.constant([[5],[2],[3],[6]])
inputs = tf.keras.layers.Input((1,))
reshape_layer = ReshapeLayer(omega=omega)
outputs = reshape_layer(inputs)
model = tf.keras.Model(inputs, outputs)
print(model(x))
tf.Tensor(
[[0 1 2 3 4 0 0 0 0 0]
 [0 1 0 0 0 0 0 0 0 0]
 [0 1 2 0 0 0 0 0 0 0]
 [0 1 2 3 4 5 0 0 0 0]], shape=(4, 10), dtype=int32)
  • Related