Несоответствие размеров при использовании модуля Pytorch LSTM - PullRequest
1 голос
/ 23 октября 2019

У меня есть предтренированная модель 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)

Скорее всего, я не определяю объект bilstm должным образом из-за отсутствия понимания ввода Pytorch nn.LSTM .

Пожалуйста, предложите.

Ответы [ 2 ]

1 голос
/ 23 октября 2019

Основы LSTM

Примечание: Нижеследующее объяснение для pytorch, когда batch_first=True

Давайте начнем с того, как выглядит развернутый LSTM

enter image description here

Выше приведен пакетный однонаправленный 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 слева направо, а другая справа налево. Таким образом, исходное скрытое состояние имеет размер no:of_layers X no:of_directions X hidden_size. Это то же самое и для состояния ячейки.

Теперь давайте создадим данные для 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=2 и input_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)
1 голос
/ 23 октября 2019

Ввод для LSTM должен быть трехмерным тензором формы (seq_len, batch, input_size). В вашем примере вы в основном предоставляете двумерный тензор формы seq_len, input_size, как вы упомянули, [-0.8264, 0.2524] является одним примером предложения.

Итак, вы можете изменить свой пример следующим образом.

# a list of 2 sentences
input_embedding = [
    torch.FloatTensor([[-0.8264],  [0.2524]]),
    torch.FloatTensor([[-0.3259],  [0.3564]])
]
for item in input_embedding:
    # item is a 2d tensor of shape `seq_len, input_size`
    # so, we unsqueeze it to make it 3d `seq_len, 1, input_size` where batch_size = 1
    y_pred = custom_model(item.unsqueeze(1))
    print(y_pred.size()) # 2, 1, 2

Надеюсь, это поможет!

...