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)