(这个答案“解决”了直接 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]]])