在时序分析中对tf.data.dataset进行批处理

问题描述

我正在考虑为时间序列LSTM模型创建管道。我有两个输入供稿,我们称它们为series1series2

我通过调用tf.data来初始化from.tensor.slices对象:

ds = tf.data.Dataset.from_tensor_slices((series1,series2))

我将它们进一步分批到设置了窗口大小的窗口中,并在窗口之间移动1:

ds = ds.window(window_size + 1,shift=1,drop_remainder=True)

在这一点上,我想尝试一下如何将它们组合在一起。我想产生一个如下所示的输入作为示例:

series1 = [1,2,3,4,5]
series2 = [100,200,300,400,500]

batch 1: [1,100,200]
batch 2: [2,300]
batch 3: [3,400]

因此每个批次将返回series1的两个元素,然后返回series2的两个元素。此代码段不能单独进行批处理:

ds = ds.map(lambda s1,s2: (s1.batch(window_size + 1),s2.batch(window_size + 1))

因为它返回两个数据集对象的映射。由于它们是对象,因此无法下标,因此这也不起作用:

ds = ds.map(lambda s1,s2: (s1[:2],s2[:2]))

我确定解决方案是使用.apply自定义lambda函数。非常感谢您的帮助。

编辑

我也在寻找产生代表该系列下一个元素的标签。因此,例如,这些批次将产生以下结果:

batch 1: (tf.tensor([1,200]),tf.tensor([3]))
batch 2: (tf.tensor([2,300]),tf.tensor([4]))
batch 3: (tf.tensor([3,400]),tf.tensor([5]))

[3][4][5]代表series1的下一个要预测的元素。

解决方法

解决方案是分别打开两个数据集的窗口,将它们.zip()在一起,然后.concat()将元素包括标签。

ds = tf.data.Dataset.from_tensor_slices(series1)
ds = ds.window(window_size + 1,shift=1,drop_remainder=True)
ds = ds.flat_map(lambda window: window.batch(window_size + 1))
ds = ds.map(lambda window: (window[:-1],window[-1]))

ds2 = tf.data.Dataset.from_tensor_slices(series2)
ds2 = ds2.window(window_size,drop_remainder=True)
ds2 = ds2.flat_map(lambda window: window.batch(window_size))

ds = tf.data.Dataset.zip((ds,ds2))
ds = ds.map(lambda i,j: (tf.concat([i[0],j],axis=0),i[-1]))

返回:

(<tf.Tensor: shape=(7,),dtype=int32,numpy=array([  1,2,3,100,200,300])>,<tf.Tensor: shape=(),numpy=4>)
(<tf.Tensor: shape=(7,numpy=array([  2,4,300,400])>,numpy=5>)
(<tf.Tensor: shape=(7,numpy=array([  3,5,400,500])>,numpy=6>)
,

我认为这是您所缺少的行:

ds = ds.batch(2).map(lambda x,y: (tf.concat([x,y],axis=0)))

完整示例:

import tensorflow as tf

series1 = tf.range(1,16)
series2 = tf.range(100,1600,100)

ds = tf.data.Dataset.from_tensor_slices((series1,series2))

ds = ds.batch(2).map(lambda x,axis=0)))

for row in ds:
    print(row)
tf.Tensor([  1   2 100 200],shape=(4,dtype=int32)
tf.Tensor([  3   4 300 400],dtype=int32)
tf.Tensor([  5   6 500 600],dtype=int32)
tf.Tensor([  7   8 700 800],dtype=int32)
tf.Tensor([   9   10  900 1000],dtype=int32)
tf.Tensor([  11   12 1100 1200],dtype=int32)
tf.Tensor([  13   14 1300 1400],dtype=int32)
,

这是我处理时间序列数据时的解决方案。

dataset = tf.data.Dataset.from_tensor_slices(series)
dataset = dataset.window(window_size + 1,drop_remainder=True)
dataset = dataset.flat_map(lambda window: window.batch(window_size + 1))
dataset = dataset.shuffle(shuffle_buffer).map(lambda window: (window[:-1],window[-1]))
dataset = dataset.batch(batch_size).prefetch(1)

下一行对于将窗口分为xs和ys很重要。

dataset.shuffle(shuffle_buffer).map(lambda window: (window[:-1],window[-1]))

虽然使用shuffle并不重要,但是您只能使用map函数将窗口分为xs和ys。