确定具有整数序列目标的 RNN 的正确形状

Determining the Right Shape for a RNN with a Integer Sequence Target

我正在尝试在 Tensorflow 中构建一个基于 RNN 的模型,该模型将一系列分类值作为输入,并将一系列分类值作为输出。

例如,如果我有 30 个值的序列,前 25 个将是训练数据,最后 5 个将是目标。想象一下,数据就像一个人在电脑键盘上按键,并随着时间的推移记录他们的按键。

我尝试将训练数据和目标以不同的形状输入到这个模型中,但我总是收到一个错误,表明数据的形状有误。

我已经包含了一个代码示例,它应该 运行 并演示我正在尝试做什么以及我看到的失败。

在代码示例中,我使用 windows 进行批处理。因此,如果序列中有 90 个值,则前 25 个值将是第一批的训练数据,接下来的 5 个值将是目标。下一批将是接下来的 30 个值(25 个训练值,5 个目标值)。

import numpy as np
import tensorflow as tf
from tensorflow import keras 

num_categories = 20
data_sequence = np.random.choice(num_categories, 10000)

def create_target(batch):
  X = tf.cast(batch[:,:-5][:,:,None], tf.float32)
  Y = batch[:,-5:][:,:,None]
  return X,Y

def add_windows(data):
  data = tf.data.Dataset.from_tensor_slices(data)
  return data.window(20, shift=1, drop_remainder=True)

dataset = tf.data.Dataset.from_tensor_slices(data_sequence)
dataset = dataset.window(30, drop_remainder=True)
dataset = dataset.flat_map(lambda x: x.batch(30))
dataset = dataset.batch(5)
dataset = dataset.map(create_target)

model = keras.models.Sequential([
  keras.layers.SimpleRNN(20, return_sequences=True),
  keras.layers.SimpleRNN(20, return_sequences=True),
  keras.layers.TimeDistributed(keras.layers.Dense(num_categories, activation="softmax"))                           
])

optimizer = keras.optimizers.Adam()
model.compile(loss="sparse_categorical_crossentropy", optimizer=optimizer)
model.fit(dataset, epochs=1)

当我运行上面的代码时得到的错误是

Node: 'sparse_categorical_crossentropy/SparseSoftmaxCrossEntropyWithLogits/SparseSoftmaxCrossEntropyWithLogits'
logits and labels must have the same first dimension, got logits shape [125,20] and labels shape [25]

我也试过下面的模型,但是错误都是类似的。

model = keras.models.Sequential([
  keras.layers.SimpleRNN(20, return_sequences=True),
  keras.layers.SimpleRNN(20),
  keras.layers.Dense(num_categories, activation="softmax"))                           
])

有没有人对我需要做什么才能使它正常工作有任何建议?

谢谢。

我想通了这个问题。训练数据和目标的时间维度的大小需要相同。

如果你看我原来的示例代码,训练数据有这些形状 X.shape = (1, 25, 1) Y.shape = (1, 5, 1)

要修复它,时间维度应该相同。

X.shape = (1, 15, 1) Y.shape = (1, 15, 1)

这是让模型训练的更新函数。请注意,我所做的只是更新数组大小,使它们大小相等。因为原数组长度为30,所以使用15的值。

def create_target(batch):
  X = tf.cast(batch[:,:-15][:,:,None], tf.float32)
  Y = batch[:,-15:][:,:,None]
  return X,Y