TensorFlow中如何为RNN输入可变时间步长的数据
tf.data.Dataset.from_generator Let's fix your dataset setup step by step, since you're dealing with variable-length sequences which from_tensor_slices can't handle directly. Here's the complete, up-to-date solution tailored to your data:
Step 1: Correct from_generator Setup with output_signature
First, let's define your dataset properly, including both x_train and y_train. The key is to specify the output_signature to match the shape and dtype of your variable-length inputs and scalar labels:
import tensorflow as tf import numpy as np # Your original data 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] # Build the dataset dataset = tf.data.Dataset.from_generator( # Generator yields (x, y) pairs lambda: zip(x_train, y_train), output_signature=( # x is a variable-length 1D tensor; shape=(None,) means variable length tf.TensorSpec(shape=(None,), dtype=tf.as_dtype(x_train[0].dtype)), # y is a scalar tensor tf.TensorSpec(shape=(), dtype=tf.as_dtype(type(y_train[0]))) ) )
What's happening here?
- The generator uses
zip(x_train, y_train)to yield pairs of your input sequences and their corresponding labels. output_signatureis a tuple that tells TensorFlow the expected structure of each generator output:- For
x:shape=(None,)explicitly signals that each sequence can have variable length. We usetf.as_dtype(x_train[0].dtype)to auto-match your numpy array's dtype (no hardcoding!). - For
y:shape=()defines a scalar value, which matches your integer labels.
- For
Step 2: Prepare for RNN Training (Padding Batches)
Since RNNs can handle variable-length sequences, but batch training requires uniform tensor shapes, you'll need to pad sequences in each batch to the length of the longest sequence in that batch:
# Pad sequences in each batch to the maximum length in the batch dataset = dataset.padded_batch( batch_size=2, # Adjust to your preferred batch size padded_shapes=( (None,), # Pad x sequences to variable batch-specific length () # No padding needed for scalar labels ) )
If you want consistent padding across all batches (e.g., pad to the longest sequence in the entire dataset), you can replace (None,) with (max_seq_len,) where max_seq_len = max(len(x) for x in x_train).
Step 3: Adapt Your Model for Variable-Length Inputs
Your existing model with the Lambda layer works great here—since the padded batches will have shape (batch_size, seq_len), the expand_dimension function adds a feature dimension (required for LSTM, which expects input shape (seq_len, features)):
from tensorflow.keras import models, layers def expand_dimension(x): return tf.expand_dims(x, axis=-1) model = models.Sequential([ # Input shape accepts variable-length sequences: (None,) layers.Lambda(expand_dimension, input_shape=[None]), layers.LSTM(units=64, activation='tanh'), layers.Dense(units=1) ]) # Compile and test the model model.compile(optimizer='adam', loss='mse') model.fit(dataset, epochs=5)
Why this works:
- The
input_shape=[None]tells Keras to accept sequences of any length. - The
Lambdalayer converts each batch from(batch_size, seq_len)to(batch_size, seq_len, 1), which is the correct input shape for LSTM layers.
Key Notes
- Avoid using
from_tensor_slicesfor variable-length sequences: it requires all input tensors to have identical shapes, which isn't the case here. - Always match
output_signaturedtypes to your source data to avoid type mismatch errors.
内容的提问来源于stack exchange,提问作者Fab

