Tensorflow 2.8.0 - 自定义层不适用于 tf.map_fn(tf.range,...)

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

亲爱的 Whosebug 社区,

我目前正在尝试创建一个自定义层,该层将整数输入的每个值转换为长度为“omega”的向量。目前,我将 tensorflow 函数 tf.map_fn 与函数 tf.range 结合起来,创建一个参差不齐的张量,然后用零填充该张量。

自定义图层定义如下:

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

我得到的错误信息如下:

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

in user code:

    File "C:\Users\User\AppData\Local\Temp\ipykernel_1390449166236.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

我试过的是:

-) 我尝试更改输入 -> 输入 [:,1],但这只会将错误消息更改为

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

in user code:

    File "C:\Users\User\AppData\Local\Temp\ipykernel_1390417026906.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


示例:

输入的形式应为 (shape=[None,1]): 示例:

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]]

有人知道这个问题的解决方案吗?

尝试使用 tf.while_looptf.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)