Keras LSTM - 使用来自生成器的 Tensorflow 数据集 API 提供序列数据
Keras LSTM - feed sequence data with Tensorflow dataset API from the generator
我正在尝试解决如何将数据提供给 LSTM 模型进行训练的问题。 (我将在下面的示例中简化问题。)我的数据集中的 csv 文件中有以下数据格式。
Timestep Feature1 Feature2 Feature3 Feature4 Output
1 1 2 3 4 a
2 5 6 7 8 b
3 9 10 11 12 c
4 13 14 15 16 d
5 17 18 19 20 e
6 21 22 23 24 f
7 25 26 27 28 g
8 29 30 31 32 h
9 33 34 35 36 i
10 37 38 39 40 j
任务是根据最近 3 个时间步长的数据估计任何未来时间步长的输出。部分输入输出示例如下:
示例 1:
输入:
Timestep Feature1 Feature2 Feature3 Feature4
1 1 2 3 4
2 5 6 7 8
3 9 10 11 12
输出:c
示例 2:
输入:
Timestep Feature1 Feature2 Feature3 Feature4
2 5 6 7 8
3 9 10 11 12
4 13 14 15 16
输出:d
示例 3:
输入:
Timestep Feature1 Feature2 Feature3 Feature4
3 9 10 11 12
4 13 14 15 16
5 17 18 19 20
输出:e
并且在将数据提供给模型时,我想以某种方式打乱数据,这样我就不会在训练时提供连续的序列。
换句话说,理想情况下,我想在一个步骤中提供时间步长 3,4,5
之类的数据序列,下一步可能是时间步长 5,6,7
,下一步可能是 2,3,4
,等等在..
而且我最好不想首先将数据作为 1,2,3
,然后是 2,3,4
,然后是 3,4,5
,依此类推...
在训练我的 LSTM 网络时,我使用的是带有 Tensorflow 后端的 Keras。我想在将数据提供给 fit_generator(...)
函数时使用生成器。
我的愿望是使用 Tensorflow 的数据集 API 从 csv 文件中获取数据。但是我不知道如何使生成器 return 满足我的需要。
如果我用 Tensorflow 的数据集 API 打乱数据,它会破坏时间步长的顺序。生成器还应该 return 包含多个序列示例的批次。例如,如果批量大小为 2,则可能需要 return 2 个序列,例如时间步长 2、3、4 和时间步长 6、7、8。
希望我能解释我的问题...是否可以在生成器函数中使用 Tensorflow 的数据集 API 来解决此类序列问题,以便我可以像上面解释的那样批量输入序列? (生成器需要 return 形状为 [batch_size, length_of_each_sequence, nr_inputs_in_each_timestep]
的数据,其中 length_of_each_sequence=3
和 nr_of_inputs_in_each_timestep=4
在我的示例中。)或者是编写生成器的最佳方法仅 Python,也许通过使用 Pandas..?
附录 1:
看到@kvish的回答后做了如下实验
import tensorflow as tf
import numpy as np
from tensorflow.contrib.data.python.ops import sliding
sequence = np.array([ [[1]], [[2]], [[3]], [[4]], [[5]], [[6]], [[7]], [[8]], [[9]] ])
labels = [1,0,1,0,1,0,1,0,1]
# create TensorFlow Dataset object
data = tf.data.Dataset.from_tensor_slices((sequence, labels))
# sliding window batch
window_size = 3
window_shift = 1
data = data.apply(sliding.sliding_window_batch(window_size=window_size, window_shift=window_shift))
data = data.shuffle(1000, reshuffle_each_iteration=False)
data = data.batch(3)
#iter = dataset.make_initializable_iterator()
iter = tf.data.Iterator.from_structure(data.output_types, data.output_shapes)
el = iter.get_next()
# create initialization ops
init_op = iter.make_initializer(data)
NR_EPOCHS = 2
with tf.Session() as sess:
for e in range (NR_EPOCHS):
print("\nepoch: ", e, "\n")
sess.run(init_op)
print("1 ", sess.run(el))
print("2 ", sess.run(el))
print("3 ", sess.run(el))
这是输出:
epoch: 0
1 (array([[[[6]],[[7]],[[8]]], [[[1]],[[2]],[[3]]], [[[2]],[[3]],[[4]]]]),
array([[0, 1, 0], [1, 0, 1], [0, 1, 0]], dtype=int32))
2 (array([[[[7]],[[8]],[[9]]], [[[3]],[[4]],[[5]]], [[[4]],[[5]],[[6]]]]),
array([[1, 0, 1], [1, 0, 1], [0, 1, 0]], dtype=int32))
3 (array([[[[5]],[[6]],[[7]]]]), array([[1, 0, 1]], dtype=int32))
epoch: 1
1 (array([[[[2]],[[3]],[[4]]], [[[7]],[[8]],[[9]]], [[[1]],[[2]],[[3]]]]),
array([[0, 1, 0], [1, 0, 1], [1, 0, 1]], dtype=int32))
2 (array([[[[5]],[[6]],[[7]]], [[[3]],[[4]],[[5]]], [[[4]],[[5]],[[6]]]]),
array([[1, 0, 1], [1, 0, 1], [0, 1, 0]], dtype=int32))
3 (array([[[[6]],[[7]],[[8]]]]),
array([[0, 1, 0]], dtype=int32))
我还不能在 csv 文件读取上尝试它,但我认为这种方法应该工作得很好!
但在我看来,reshuffle_each_iteration
参数没有任何区别。这真的需要吗?当设置为 True
或 False
时,结果不一定相同。 reshuffle_each_iteration
参数在这里应该做什么?
我认为 可能接近您要查找的内容!
您可以通过在 windows 上滑动来创建批次,然后根据您的情况打乱输入。数据集 api 的 shuffle 函数有一个 reshuffle_after_each_iteration 参数,如果您想尝试设置随机种子并查看随机种子的顺序,您可能希望将其设置为 False输出。
我正在尝试解决如何将数据提供给 LSTM 模型进行训练的问题。 (我将在下面的示例中简化问题。)我的数据集中的 csv 文件中有以下数据格式。
Timestep Feature1 Feature2 Feature3 Feature4 Output
1 1 2 3 4 a
2 5 6 7 8 b
3 9 10 11 12 c
4 13 14 15 16 d
5 17 18 19 20 e
6 21 22 23 24 f
7 25 26 27 28 g
8 29 30 31 32 h
9 33 34 35 36 i
10 37 38 39 40 j
任务是根据最近 3 个时间步长的数据估计任何未来时间步长的输出。部分输入输出示例如下:
示例 1: 输入:
Timestep Feature1 Feature2 Feature3 Feature4
1 1 2 3 4
2 5 6 7 8
3 9 10 11 12
输出:c
示例 2: 输入:
Timestep Feature1 Feature2 Feature3 Feature4
2 5 6 7 8
3 9 10 11 12
4 13 14 15 16
输出:d
示例 3: 输入:
Timestep Feature1 Feature2 Feature3 Feature4
3 9 10 11 12
4 13 14 15 16
5 17 18 19 20
输出:e
并且在将数据提供给模型时,我想以某种方式打乱数据,这样我就不会在训练时提供连续的序列。
换句话说,理想情况下,我想在一个步骤中提供时间步长 3,4,5
之类的数据序列,下一步可能是时间步长 5,6,7
,下一步可能是 2,3,4
,等等在..
而且我最好不想首先将数据作为 1,2,3
,然后是 2,3,4
,然后是 3,4,5
,依此类推...
在训练我的 LSTM 网络时,我使用的是带有 Tensorflow 后端的 Keras。我想在将数据提供给 fit_generator(...)
函数时使用生成器。
我的愿望是使用 Tensorflow 的数据集 API 从 csv 文件中获取数据。但是我不知道如何使生成器 return 满足我的需要。 如果我用 Tensorflow 的数据集 API 打乱数据,它会破坏时间步长的顺序。生成器还应该 return 包含多个序列示例的批次。例如,如果批量大小为 2,则可能需要 return 2 个序列,例如时间步长 2、3、4 和时间步长 6、7、8。
希望我能解释我的问题...是否可以在生成器函数中使用 Tensorflow 的数据集 API 来解决此类序列问题,以便我可以像上面解释的那样批量输入序列? (生成器需要 return 形状为 [batch_size, length_of_each_sequence, nr_inputs_in_each_timestep]
的数据,其中 length_of_each_sequence=3
和 nr_of_inputs_in_each_timestep=4
在我的示例中。)或者是编写生成器的最佳方法仅 Python,也许通过使用 Pandas..?
附录 1:
看到@kvish的回答后做了如下实验
import tensorflow as tf
import numpy as np
from tensorflow.contrib.data.python.ops import sliding
sequence = np.array([ [[1]], [[2]], [[3]], [[4]], [[5]], [[6]], [[7]], [[8]], [[9]] ])
labels = [1,0,1,0,1,0,1,0,1]
# create TensorFlow Dataset object
data = tf.data.Dataset.from_tensor_slices((sequence, labels))
# sliding window batch
window_size = 3
window_shift = 1
data = data.apply(sliding.sliding_window_batch(window_size=window_size, window_shift=window_shift))
data = data.shuffle(1000, reshuffle_each_iteration=False)
data = data.batch(3)
#iter = dataset.make_initializable_iterator()
iter = tf.data.Iterator.from_structure(data.output_types, data.output_shapes)
el = iter.get_next()
# create initialization ops
init_op = iter.make_initializer(data)
NR_EPOCHS = 2
with tf.Session() as sess:
for e in range (NR_EPOCHS):
print("\nepoch: ", e, "\n")
sess.run(init_op)
print("1 ", sess.run(el))
print("2 ", sess.run(el))
print("3 ", sess.run(el))
这是输出:
epoch: 0
1 (array([[[[6]],[[7]],[[8]]], [[[1]],[[2]],[[3]]], [[[2]],[[3]],[[4]]]]),
array([[0, 1, 0], [1, 0, 1], [0, 1, 0]], dtype=int32))
2 (array([[[[7]],[[8]],[[9]]], [[[3]],[[4]],[[5]]], [[[4]],[[5]],[[6]]]]),
array([[1, 0, 1], [1, 0, 1], [0, 1, 0]], dtype=int32))
3 (array([[[[5]],[[6]],[[7]]]]), array([[1, 0, 1]], dtype=int32))
epoch: 1
1 (array([[[[2]],[[3]],[[4]]], [[[7]],[[8]],[[9]]], [[[1]],[[2]],[[3]]]]),
array([[0, 1, 0], [1, 0, 1], [1, 0, 1]], dtype=int32))
2 (array([[[[5]],[[6]],[[7]]], [[[3]],[[4]],[[5]]], [[[4]],[[5]],[[6]]]]),
array([[1, 0, 1], [1, 0, 1], [0, 1, 0]], dtype=int32))
3 (array([[[[6]],[[7]],[[8]]]]),
array([[0, 1, 0]], dtype=int32))
我还不能在 csv 文件读取上尝试它,但我认为这种方法应该工作得很好!
但在我看来,reshuffle_each_iteration
参数没有任何区别。这真的需要吗?当设置为 True
或 False
时,结果不一定相同。 reshuffle_each_iteration
参数在这里应该做什么?
我认为
您可以通过在 windows 上滑动来创建批次,然后根据您的情况打乱输入。数据集 api 的 shuffle 函数有一个 reshuffle_after_each_iteration 参数,如果您想尝试设置随机种子并查看随机种子的顺序,您可能希望将其设置为 False输出。