Быстрый способ создания нескольких трехмерных тензоров формы (1, 1, 256) и (10, 1, 256) в PyTorch и Numpy - PullRequest
0 голосов
/ 28 мая 2018

Я пытаюсь адаптировать модель seq2seq для моей собственной задачи, https://github.com/spro/practical-pytorch/blob/master/seq2seq-translation/seq2seq-translation.ipynb

У меня есть два тензора на этапе декодера

rnn_output: (1, 1, 256)       # time_step x batch_size x hidden_dimension
encoder_inputs: (10, 1, 256)  # seq_len   x batch_size x hidden_dimension

Их нужно умножить, чтобы получить оценку внимания(до softmax) формы

attn_score: (10, 1, 1) 

Какой лучший способ сделать это?Похоже, что в ноутбуке используется цикл for, лучше ли использовать матричное умножение?

Ответы [ 2 ]

0 голосов
/ 28 мая 2018

Нет опыта работы с pytorch, но может ли что-то вроде этой работы?

torch.einsum('ijk,abk->abc', (rnn_output, encoder_inputs))

Она берет произведение точек над последней осью и добавляет пару пустых осей назад.

Что-топодобное может быть достигнуто с помощью чистого numpy (pytorch 0.4 еще не имеет обозначения ...)

np.einsum('...ik,...jk', rnn_output.numpy(), encoder_inputs.numpy())

Или с np.tensordot

np.tensordot(rnn_output.numpy(), encoder_inputs.numpy(), axes=[2,2])

Но здесь вы получитеВыходная форма: (1, 1, 10, 1)

Что вы можете исправить, сжимая и снова растягивая ( почти наверняка должен быть какой-то более чистый способ сделать это )

 np.tensordot(rnn_output.numpy(), encoder_inputs.numpy(), axes=[2,2]).squeeze()[..., None, None]
0 голосов
/ 28 мая 2018

Пример использования torch.bmm():

import torch
from torch.autograd import Variable
import numpy as np

seq_len = 10
rnn_output = torch.rand((1, 1, 256))
encoder_outputs = torch.rand((seq_len, 1, 256))

# As computed in the tutorial:
attn_score = Variable(torch.zeros(seq_len))
for i in range(seq_len):
    attn_score[i] = rnn_output.squeeze().dot(encoder_outputs[i].squeeze())
    # note: the code would fail without the "squeeze()". I would assume the tensors in
    # the tutorial are actually (,256) and (10, 256)

# Alternative using batched matrix multiplication (bmm) with some data reformatting first:
attn_score_v2 = torch.bmm(rnn_output.expand(seq_len, 1, 256),
                          encoder_outputs.view(seq_len, 256, 1)).squeeze()

# ... Interestingly though, there are some numerical discrepancies between the 2 methods:
np.testing.assert_array_almost_equal(attn_score.data.numpy(), 
                                     attn_score_v2.data.numpy(), decimal=5)
# AssertionError: 
# Arrays are not almost equal to 5 decimals
# 
# (mismatch 30.0%)
#  x: array([60.32436, 69.04288, 72.04784, 70.19503, 71.75543, 67.45459,
#        63.01708, 71.70189, 63.07552, 67.48799], dtype=float32)
#  y: array([60.32434, 69.04287, 72.0478 , 70.19504, 71.7554 , 67.4546 ,
#        63.01709, 71.7019 , 63.07553, 67.488  ], dtype=float32)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...