首页 > 解决方案 > 使用 Pytorch LSTM 模块时尺寸不匹配

问题描述

我有一个 pytorch 预训练模型,我从中为一些输入句子生成特征/嵌入。特征本质上是torch对象。例如input_embedding,一个句子的示例(火炬对象列表)如下所示

[tensor([-0.8264,  0.2524], device='cuda:0', grad_fn=<SelectBackward>)]

现在,我想通过一个自定义模型传递这个嵌入,该模型基本上是一个双向 LSTM:

def custom_model(input_embedding):
    #initialize BiLSTM
    bilstm = torch.nn.LSTM(input_size=1, hidden_size=1, num_layers=1, batch_first=False, bidirectional=True)
    #feed input to bilstm object
    bi_output, bi_hidden = bilstm(input_embedding)
    # more code ....
    return F.softmax(x)

我想将我的传递input_embedding给这个自定义模型以获得如下预测输出:

for item in input_embedding:
    y_pred = biLSTM_single_sentence_student_model(item)

但它bi_output, bi_hidden = bilstm(input_embedding)在线上抛出错误说:

IndexError: Dimension out of range (expected to be in range of [-1, 0], but got 1)

由于我对Pytorch nn.LSTM inputbilstm缺乏了解,很可能我没有正确定义对象。

请建议。

标签: pythonmachine-learningdeep-learningpytorchlstm

解决方案


LSTM 基础知识

注意:下面的解释是针对 pytorch 时的batch_first=True

让我们先看看展开的 LSTM 的样子

在此处输入图像描述

上图是一个堆叠的单向 LSTM。

  • 堆叠的 LSTM 有多个 LSTM 单元相互堆叠。堆叠 LSTM 的数量由层数 ( no:of_layers) 定义。
  • LSTM 单元在输入上随时间展开。展开次数由输入序列的长度决定 ( seq_len)
  • 展开的 LSTM 的每个输入都是一定大小的向量(由 定义input_size
  • 展开的 LSTM 的输出是一个特定大小的向量(由 定义hidden_size)。这是使用对输入、最后隐藏状态和当前单元状态的一系列操作来计算的。
  • 通常,训练发生在一批数据(前向道具和后向道具)上,而不是一次针对单个输入样本。

定义

所以要使用\定义一个 LSTM,我们需要定义以下信息

  1. 输入:大小batch_size x seq_len x input_size
  2. 输出:大小batch_size x seq_len x hidden_size

LSTM 定义为提供给展开的 LSTM 单元的向量大小和从展开的 LSTM 单元返回的输出向量大小

lstm = nn.LSTM(2, 5, batch_first=True) 

定义一个 LSTM,它接受一个向量或大小为 2(每次展开)并返回一个大小为 5(每次展开)的向量

展开

我们通过给 LSTM 提供一批数据并提供可选的初始隐藏状态和单元状态来计算 LSTM 的输出。

初始隐藏状态:在双向 LSTM 中,一个 LSTM 角色从左到右,另一个从右到左。所以初始隐藏状态的大小为no:of_layers X no:of_directions X hidden_size。这对于单元状态也是完全相同的。

现在让我们为 a 创建数据,batch_size=32其中每个输入的序列为 10,向量为 2。

X = torch.randn(32,10,2)

可选的隐藏状态和单元状态

h = torch.randn(1*1, 32, 5)
c = torch.randn(1*1, 32, 5)

最后让我们展开并计算输出

out, hidden = lstm(X, (h,c))

你的问题

在您的情况下,您有一个张量列表,每个张量对应于样本的特征。我们需要将其转换为形状张量,batch_size x seq_len x input_size其中张量的batch_size数量seq_len=2input_size=1

工作代码

class CustomModel(nn.Module):
    def __init__(self):
        super(CustomModel, self).__init__()

        input_size = 1

        hidden_size = 6
        target_size = 2

        self.lstm = nn.LSTM(input_size, hidden_size, batch_first=True) 
        self.linear = nn.Linear(hidden_size, target_size)

    def forward(self, X):
        out, hidden = self.lstm(X)
        y_hat = self.linear(hidden[0][0])
        y_hat = F.log_softmax(y_hat, dim=1)
        return y_hat


data = [torch.randn(2) for i in range(100)]
X = torch.stack(data)
X = X.unsqueeze(-1)

model = CustomModel()


for epoch in range(1):  
        tag_scores = model(X)  
        print (tag_scores)

推荐阅读