了解 TensorFlow LSTM 输入形状
Posted
技术标签:
【中文标题】了解 TensorFlow LSTM 输入形状【英文标题】:Understanding Tensorflow LSTM Input shape 【发布时间】:2017-01-12 11:11:00 【问题描述】:我有一个数据集 X,它包含 N = 4000 个样本,每个样本包含 d = 2 个特征(连续值),跨越 t = 10 次步骤。在时间步骤 11,我也有每个样本的相应“标签”,它们也是连续值。
目前我的数据集的形状是 X:[4000,20],Y:[4000]。
我想使用 TensorFlow 训练一个 LSTM 来预测 Y(回归)的值,给定 d 特征的 10 个先前输入,但我在 TensorFlow 中实现这一点很困难。
我目前遇到的主要问题是了解 TensorFlow 如何期望输入被格式化。我见过各种例子,例如this,但这些例子处理的是一大串连续的时间序列数据。我的数据是不同的样本,每个样本都是独立的时间序列。
【问题讨论】:
嗨,我正在尝试实现与您所做的非常相似的事情,希望您能给我一些提示,因为 tensorflow 对我来说仍然令人难以置信。对于您的设置,输入文件的实际外观如何?每个样本基本上是一个长度为 10 的列表,每个元素包含 2 个特征,并且每个样本都有一个标签吗?例如[[f1,f2], [f1,f2], ...] 【参考方案1】:documentation of tf.nn.dynamic_rnn
声明:
inputs
:RNN 输入。如果time_major == False
(默认),这必须是一个形状的张量:[batch_size, max_time, ...]
,或此类元素的嵌套元组。
在您的情况下,这意味着输入的形状应为[batch_size, 10, 2]
。与其一次训练所有 4000 个序列,不如在每次训练迭代中只使用 batch_size
其中许多序列。类似以下的东西应该可以工作(为清楚起见添加了重塑):
batch_size = 32
# batch_size sequences of length 10 with 2 values for each timestep
input = get_batch(X, batch_size).reshape([batch_size, 10, 2])
# Create LSTM cell with state size 256. Could also use GRUCell, ...
# Note: state_is_tuple=False is deprecated;
# the option might be completely removed in the future
cell = tf.nn.rnn_cell.LSTMCell(256, state_is_tuple=True)
outputs, state = tf.nn.dynamic_rnn(cell,
input,
sequence_length=[10]*batch_size,
dtype=tf.float32)
从documentation 开始,outputs
的形状将是 [batch_size, 10, 256]
,即每个时间步有一个 256 输出。 state
将是 tuple 的形状 [batch_size, 256]
。你可以从中预测你的最终值,每个序列一个:
predictions = tf.contrib.layers.fully_connected(state.h,
num_outputs=1,
activation_fn=None)
loss = get_loss(get_batch(Y).reshape([batch_size, 1]), predictions)
outputs
和 state
形状中的数字 256 分别由 cell.output_size
确定。 cell.state_size
。像上面一样创建LSTMCell
时,这些是相同的。另请参阅LSTMCell documentation。
【讨论】:
感谢您的回复!我会尽快尝试一下,如果它解决了我的问题,请告诉您。但是有一个问题:tf.nn.rnn_cell.LSTMCell(256, state_is_tuple=True) 中的 256 到底指的是什么?我已阅读文档,该值称为 n_units。这是否意味着时间步数?即LSTM单元的记忆?抱歉,我知道这是原始问题的扩展。 每个序列中的时间步数由您提供给tf.nn.dynamic_rnn
的sequence_length
参数给出。 256 是指 LSTM 内部状态的大小,每个时间步都会更新。
@fwalch 问题:您不希望用于预测的全连接层具有num_outputs=batch_size
吗?那么你的批次中每个时间序列的末尾会有一个预测?
@Engineero 全连接层的输出形状为[batch_size, num_outputs]
,即num_outputs
是批处理中每个条目的输出数。【参考方案2】:
(这个答案“解决”了直接 np.reshape() 没有按照我们想要的方式组织最终数组时的问题。如果我们想直接重塑为 3D np.reshape 会做到这一点,但请注意用于输入的最终组织)。
在我个人的尝试中,最终解决了为 RNN 提供输入形状的问题并且不再混淆,我将对此给出我的“个人”解释。
就我而言(而且我认为许多其他人的特征矩阵中可能有这种组织方案),大多数以外的博客“没有帮助”。让我们尝试一下如何将 2D 特征矩阵转换为 RNN 的 3D 形状。
假设我们的特征矩阵中有这种组织类型:我们有 5 个观察结果(即行 - 为了约定,我认为这是最合乎逻辑的术语)在每一行中,我们有每个时间步长的 2 个特征(我们有 2 个时间步长),如下所示:
(df
是为了更好地直观理解我的话)
In [1]: import numpy as np
In [2]: arr = np.random.randint(0,10,20).reshape((5,4))
In [3]: arr
Out[3]:
array([[3, 7, 4, 4],
[7, 0, 6, 0],
[2, 0, 2, 4],
[3, 9, 3, 4],
[1, 2, 3, 0]])
In [4]: import pandas as pd
In [5]: df = pd.DataFrame(arr, columns=['f1_t1', 'f2_t1', 'f1_t2', 'f2_t2'])
In [6]: df
Out[6]:
f1_t1 f2_t1 f1_t2 f2_t2
0 3 7 4 4
1 7 0 6 0
2 2 0 2 4
3 3 9 3 4
4 1 2 3 0
我们现在将使用这些值来处理它们。这里的问题是 RNN 将“时间步长”维度纳入其输入,因为它们的架构性质。我们可以将该维度想象为按照我们拥有的时间步数一个接一个地堆叠二维数组。在这种情况下,我们有两个时间步;所以我们将堆叠两个二维数组:一个用于 timestep1,一个用于 timestep2。
实际上,在我们需要进行的 3D 输入中,我们仍然有 5 个观察值。问题是我们需要以不同的方式排列它们:RNN 将获取第一个数组(即 timestep1)的第一行(或指定的批次 - 但我们在这里保持简单)和第二个堆叠数组的第一行(即时间步2)。然后是第二行......直到最后一行(在我们的示例中为第 5 行)。 So,在每个时间步的每一行中,我们需要有两个特征,当然,分开在不同的数组中,每个数组对应于它的时间步。让我们用数字来看看。
我将制作两个数组以便于理解。请记住,由于我们在 df 中的组织方案,您可能已经注意到 我们需要将前两列(即 timestep1 的特征 1 和 2)作为堆栈的第一个数组,最后两列,即第 3 和第 4,作为我们堆栈的第二个阵列,这样一切最终都变得有意义。
In [7]: arrStack1 = arr[:,0:2]
In [8]: arrStack1
Out[8]:
array([[3, 7],
[7, 0],
[2, 0],
[3, 9],
[1, 2]])
In [9]: arrStack2 = arr[:,2:4]
In [10]: arrStack2
Out[10]:
array([[4, 4],
[6, 0],
[2, 4],
[3, 4],
[3, 0]])
最后,我们唯一需要做的就是堆叠两个数组(“一个在另一个之后”),就好像它们是同一个最终结构的一部分:
In [11]: arrfinal3D = np.stack([arrStack1, arrStack2])
In [12]: arrfinal3D
Out[12]:
array([[[3, 7],
[7, 0],
[2, 0],
[3, 9],
[1, 2]],
[[4, 4],
[6, 0],
[2, 4],
[3, 4],
[3, 0]]])
In [13]: arrfinal3D.shape
Out[13]: (2, 5, 2)
就是这样:我们已经准备好将特征矩阵输入 RNN 单元,同时考虑到我们对 2D 特征矩阵的组织。
(对于所有这一切,你可以使用一个班轮:
In [14]: arrfinal3D_1 = np.stack([arr[:,0:2], arr[:,2:4]])
In [15]: arrfinal3D_1
Out[15]:
array([[[3, 7],
[7, 0],
[2, 0],
[3, 9],
[1, 2]],
[[4, 4],
[6, 0],
[2, 4],
[3, 4],
[3, 0]]])
【讨论】:
最终的 3d 形状不应该是 (5,2,2),,5 样本大小,2 代表 2 个时间步长,2 代表特征。每个堆叠的 2d 层也不应该对应不同的特征吗? 不,这不是 numpy 表示 3d 形状的方式。误解它很常见,但您可以尝试使用其他 3d 形状示例,看看它是帖子中突出显示的方式。所以,它不是 (x, y, z);相反,它是 (z, x, y)。关于你的第二个问题,这也是不正确的;时间步长是堆叠的,但每个时间步长的特征都是相同的。 但是 input_shape 不是定义为 (sample_size,timestep, features)。 ?这是 tensorflow 网站提到的关于 input_shape 的内容。 一件事是 numpy 如何表示形状,另一件事是您需要如何将它们提供给 tensorflow。在这种情况下,您将需要重塑数据以适应每个不同的 input_shape。这只是一个了解任何包之外的数据维度的练习。 我只是在尝试使用 reshape 使用 numpy。所以 numpy 将(样本大小,时间步长,特征)表示为(特征,样本大小,时间步长)。我说的对吗?以上是关于了解 TensorFlow LSTM 输入形状的主要内容,如果未能解决你的问题,请参考以下文章
如何在 MultiOutput LSTM Tensorflow 中优先考虑某些输出?
理解 LSTM 中的输入和输出形状 | tf.keras.layers.LSTM(以及对于return_sequences的解释)