简体   繁体   English

Tensorflow:如何将可变时间步长输入提供给 RNN

[英]Tensorflow: how to feed a variable-time-step input to a RNN

I have a simple X_train and Y_train data:我有一个简单的 X_train 和 Y_train 数据:

x_train = [
  array([ 6,  1,  9, 10,  7,  7,  1,  9, 10,  3, 10,  1,  4]), 
  array([ 2,  8,  8,  1,  1,  4,  2,  5,  1,  2,  7,  2,  1,  1, 4,  5, 10, 4])
]
y_train = [23, 17]

Arrays are numpy arrays. Arrays 是 numpy arrays。 I am now trying to use the tf.data.Dataset class to load these as tensors.我现在正在尝试使用tf.data.Dataset class 将这些加载为张量。 Before I have done a similar thing successfully using the following code:在我使用以下代码成功完成类似的事情之前:

    dataset = data.Dataset.from_tensor_slices((x_train, y_train))

As this input is fed into a RNN, I have used the expand_dims method in the first RNN layer (the expand_dimension is passed as a function to overcome an apparent bug in tensorflow: see https://github.com/keras-team/keras/issues/5298#issuecomment-281914537 ): As this input is fed into a RNN, I have used the expand_dims method in the first RNN layer (the expand_dimension is passed as a function to overcome an apparent bug in tensorflow: see https://github.com/keras-team/keras /issues/5298#issuecomment-281914537 ):

def expand_dimension(x):
    from tensorflow import expand_dims
    return expand_dims(x, axis=-1)

model = models.Sequential(
    [
        layers.Lambda(expand_dimension,
                      input_shape=[None]),
        layers.LSTM(units=64, activation='tanh'),
        layers.Dense(units=1)
    ]
)

This worked although because I had arrays of equal length.这虽然有效,但因为我有相同长度的 arrays。 In the example I posted instead the 1st array has 13 numbers and the 2nd one 18. In this case the method above doesn't work, and the recommended method seems to be using tf.data.Dataset.from_generator .在我发布的示例中,第一个数组有 13 个数字,第二个数组有 18 个。在这种情况下,上面的方法不起作用,推荐的方法似乎是使用tf.data.Dataset.from_generator Reading this How to use the Tensorflow Dataset Pipeline for Variable Length Inputs?阅读本文如何使用 Tensorflow 数据集管道进行可变长度输入? , the accepted solution shows something like the following would work (where I am not caring here about y_train for simplicity): ,接受的解决方案显示类似于以下内容的内容(为简单起见,我在这里不关心y_train ):

dataset = tf.data.Dataset.from_generator(lambda: x_train, 
                                         tf.as_dtype(x_train[0].dtype),
                                         tf.TensorShape([None, ]))

However, the syntax in tensorflow has changed since this answer, and now it requires to use the output_signature argument (see https://www.tensorflow.org/api_docs/python/tf/data/Dataset#from_generator ).但是,自此答案以来,tensorflow 中的语法已更改,现在需要使用output_signature参数(请参阅https://www.tensorflow/Dataset#from_docs/python.org/api_gen

I've tried different ways but I'm finding hard to understand from tensorflow documentation what the output_signature should exactly be in my case.我尝试了不同的方法,但我发现很难从 tensorflow 文档中理解output_signature在我的情况下应该是什么。 Any help would be much appreciated.任何帮助将非常感激。

Short answer is, you can define output_signature as follows.简短的回答是,您可以定义output_signature如下。

import tensorflow as tf
import numpy as np
x_train = [
  np.array([ 6,  1,  9, 10,  7,  7,  1,  9, 10,  3, 10,  1,  4]), 
  np.array([ 2,  8,  8,  1,  1,  4,  2,  5,  1,  2,  7,  2,  1,  1, 4,  5, 10, 4])
]
y_train = [23, 17]

dataset = tf.data.Dataset.from_generator(
    lambda: x_train, 
    output_signature=tf.TensorSpec(
        [None, ], 
        dtype=tf.as_dtype(x_train[0].dtype)
    )
)

I'll also expand and improve on some things you're doing here to improve your pipeline.我还将扩展和改进您在这里所做的一些事情,以改善您的管道。

Using both inputs and labels同时使用输入和标签

dataset = tf.data.Dataset.from_generator(
    lambda: zip(x_train, y_train), 
    output_signature=(
        tf.TensorSpec([None, ], dtype=tf.as_dtype(x_train[0].dtype)),
        tf.TensorSpec([], dtype=tf.as_dtype(y_train.dtype))
    )
)

for x in dataset:
  print(x)

Which would output,哪个会 output,

(<tf.Tensor: shape=(13,), dtype=int64, numpy=array([ 6,  1,  9, 10,  7,  7,  1,  9, 10,  3, 10,  1,  4])>, <tf.Tensor: shape=(), dtype=int64, numpy=23>)
(<tf.Tensor: shape=(18,), dtype=int64, numpy=
array([ 2,  8,  8,  1,  1,  4,  2,  5,  1,  2,  7,  2,  1,  1,  4,  5, 10,
        4])>, <tf.Tensor: shape=(), dtype=int64, numpy=17>)

Caveat : This can get slightly more complicated if you try to tf.data.Dataset.batch() items.警告:如果您尝试tf.data.Dataset.batch()项目,这可能会稍微复杂一些。 Then you need to use RaggedTensorSpec instead of TensorSpec .然后你需要使用RaggedTensorSpec而不是TensorSpec Also, I haven't experimented too much with feeding in ragged tensors into a RNN.此外,我还没有对将参差不齐的张量输入 RNN 进行太多实验。 But I think those are out of scope for the question you've asked.但是我认为对于您提出的问题,这些都超出了 scope 的范围。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM