
在Pytorch中,使用LSTMCell(使用nn.LSTMCell)时,我们需要了解表示输入时间序列、隐藏状态向量和细胞状态向量的张量应如何形状。在本文中,让我们假设您正在处理多变量时间序列。数据集中的每个多变量时间序列包含多个单变量时间序列。
在本文中,我们使用以下术语:
batch = 数据集中单个批次中的多变量时间序列数量
input_features = 单个多变量时间序列中的单变量时间序列数量
time_steps = 每个多变量时间序列中的时间步数
传递给LSTMCell的多变量时间序列批次应该是一个形状为(time_steps, batch, input_features)的张量
以下图片给出了输入形状的理解:

LSTMCell的输入是以特定方式给出的。基本上,整个多变量时间序列不作为时间序列的输入给出。在MTS中的特定时间步的向量x_t作为LSTMCell的输入。为了处理单个时间步的向量,LSTMCell需要一个单个的隐藏状态向量作为输入的一部分,以及一个单个的细胞状态向量作为输入的一部分。它们分别表示为h_0和c_0。LSTMCell的输出将是在处理下一个时间步的输入向量x_t+1时使用的隐藏状态和细胞状态。这些隐藏状态和细胞状态分别表示为h_1和c_1。LSTMCell在循环中调用,将h_1和c_1作为后续时间步的h_0和c_0传入。这个概念在以下代码片段中说明。
在初始化LSTMCell对象时,应给出参数input_features和hidden_size。
这里,input_features = 单个多变量时间序列中的单变量时间序列数量(与上述input_features相同)
hidden_size = 隐藏状态向量中的维数。这个大小也应该用于细胞状态向量中的维数。
LSTMCell中的隐藏状态和细胞状态的初始值应该创建为形状为(batch, hidden_size)的张量。这里,batch应与输入多变量时间序列中的batch相匹配。这意味着对于输入批次中的每个MTS,都有一个相应的隐藏状态和细胞状态。
初始隐藏状态和初始细胞状态的时间序列应作为前向传播通过LSTMCell的输入。
将输入MTS的特定时间步的向量、初始隐藏状态和初始细胞状态通过LSTMCell对象的前向传播应按以下格式进行:
LSTMCell(x_t, (h_0, c_0))
以下图片给出了隐藏状态和细胞状态形状的理解:

以下是一个示例代码。代码的解释如下。
import torch
import torch.nn as nn
lstm_0 = nn.LSTMCell(10, 20) # (input_features, hidden_size)
inp = torch.randn(7, 3, 10) # (time_steps, batch, input_features) -> input time series
hx = torch.randn(3, 20) # (batch, hidden_size) -> initial value of hidden state
cx = torch.randn(3, 20) # (batch, hidden_size) -> initial value of cell state
for i in range(inp.size()[0]):
hx, cx = lstm_0(inp[i], (hx, cx)) # input通过LSTMCell进行前向传播
output.append(hx)
output = torch.stack(output, dim=0)
调用nn.LSTMCell()将调用__init__()魔术方法并创建一个LSTMCell对象。在上面的代码中,该对象被引用为lstm_0。
通常情况下的RNN(LSTM是RNN的一种类型),输入时间序列的每个时间步都应按顺序逐个传入RNN中以由RNN进行处理。
为了使用LSTMCell批量处理多变量时间序列,批次中所有MTS的每个时间步都应顺序通过LSTMCell进行传递。
这通过for循环实现。循环遍历MTS的每个时间步(inp.size()的第一个维度是时间步数),并将每个MTS中的时间步向量并行地传递到LSTMCell中。对LSTMCell的单个调用仅处理MTS中一个时间步的向量。
for循环中调用lstm_0(inp[i], (hx, cx))的输出是为每个时间步创建下一个隐藏状态和细胞状态。输出的隐藏状态(hx)和细胞状态(cx)根据先前的hx和cx进行递归计算。
输出:(h_1, c_1)
此输出对整个批次中的每个时间序列计算。输出形状为(batch, hidden_size)。
以下图片展示了输出的隐藏状态和细胞状态的形状:

在输入批次中为每个时间步创建的这些计算hx被附加到输出张量中,然后沿着0轴堆叠。因此,输出的维度为(time_steps, batch, hidden_size)。
对于上面的代码示例,以下是输出:
tensor([[[ 0.0087, 0.0365, -0.1233, -0.2641, 0.2908, -0.5075, 0.2587, 0.1057, -0.2079, -0.2327, 0.1390, 0.1023, -0.1186, 0.3302, 0.1139, 0.1591, -0.0264, -0.0499, 0.0153, 0.3881], [ 0.3585, -0.4133, -0.0259, 0.2490, -0.0936, -0.2756, -0.1941, -0.0967, 0.1501, -0.0334, -0.1904, -0.3945, -0.1036, -0.2091, 0.0545, 0.1937, -0.2338, 0.0382, 0.2344, 0.1169], [-0.2532, 0.0745, -0.0329, 0.0971, -0.1057, -0.0383, 0.1328, 0.1263, -0.1422, 0.0351, 0.3957, -0.4115, -0.2951, -0.5560, 0.1941, 0.0100, 0.3028, -0.1803, 0.0028, 0.3210]], [[ 0.1105, -0.1295, -0.0636, -0.2510, 0.1923, -0.2457, 0.2401, 0.1379, -0.1373, -0.2451, 0.0387, 0.1004, -0.0580, 0.3430, -0.0149, 0.1827, -0.0229, -0.2061, 0.1718, 0.3146], [ 0.2741, -0.2413, -0.1310, 0.1206, 0.0379, -0.1738, -0.0568, 0.0417, 0.0756, 0.1020, 0.0262, -0.3280, -0.0352, -0.1713, 0.1065, 0.0458, -0.3404, -0.0795, 0.0586, 0.0026], [-0.0112, 0.0883, -0.1755, -0.0438, 0.0193, 0.0151, 0.1010, 0.1614, -0.0524, 0.0970, 0.2092, -0.3518, -0.0715, -0.3941, 0.1422, 0.1164, 0.2946, -0.1919, 0.1493, 0.1203]]], grad_fn=<StackBackward0>)
对于输入中的每个时间步(输入中的 time_steps = 2),都会创建一个数组(创建了 2 个数组)。每个数组都包含批次中每个 MTS 的数组(batch_size = 3)。对于 MTS 中的每个时间步,我们会得到一个 hidden_size 维度的隐藏状态向量输出(这里 hidden_size = 20)。因此,对于每个时间步,MTS 的值是一个向量。该向量在一个时间步中被映射为一个 20 维的 hidden_state 向量。
下图展示了输出多变量时间序列批次的形状:

如果在上面的代码中打印 hx,对于一个时间步(循环中的一个迭代),输出如下:
tensor([[ 0.1034, -0.0192, -0.0581, -0.0772, -0.1578, -0.1450, 0.0377, -0.0013, -0.2641, -0.1821, 0.0431, -0.2262, 0.3025, 0.0952, 0.4113, -0.2968, -0.4377, 0.0794, 0.3683, -0.0021], [ 0.0309, 0.3957, 0.2143, 0.1020, 0.0640, -0.0628, 0.4390, 0.1818, 0.0373, 0.2497, -0.1768, -0.2038, -0.1249, -0.2995, 0.0786, -0.0522, -0.0080, -0.3095, -0.0815, 0.2874], [-0.2458, 0.1622, 0.2564, -0.3136, 0.0631, 0.0643, 0.4036, 0.3293, -0.1806, -0.0251, -0.4505, -0.1437, -0.1718, -0.0479, -0.1116, -0.1065, -0.3289, 0.1137, 0.1160, 0.1227]], grad_fn=<MulBackward0>)
它有一个对应于一个时间步的数组。在这个时间步内,有 3 个数组,对应于批次中的 3 个 MTS。每个对应于一个 MTS 的数组都有一个 20 维的隐藏向量。因此,一个时间步的输出是(batch, hidden_size)。
可以通过下图理解这个输出大小:

nn.LSTMCell 的初始化参数是:
input_size
hidden_size
bias
device
dtype
它没有 num_layers。因为这是一个单层的 cell,所以不能有多个 LSTM 层。