Как применить пользовательскую функцию к определенным столбцам в матрице в PyTorch - PullRequest
0 голосов
/ 29 апреля 2018

У меня есть тензор размера [150, 182, 91], первая часть - это просто размер партии, а интересующая меня матрица - 182x91.

Мне нужно запустить функцию на матрице 182x91 для каждого из 50 измерений в отдельности.

Мне нужно получить диагональную матричную полосу матрицы 182x91, и я использую следующую функцию (основываясь на моем предыдущем вопросе: Автоматическое получение диагональной матричной полосы в numpy или pytorch ):

 def stripe(a):

    i, j = a.size()
    assert (i >= j)

    out = torch.zeros((i - j + 1, j))
    for diag in range(0, i - j + 1):
        out[diag] = torch.diag(a, -diag)
    return out

Функция stripe ожидает матрицу размера IxJ и не может иметь дело с 3-м измерением.

Итак, когда я запускаю это:

some_matrix = x # <class 'torch.autograd.variable.Variable'> torch.Size([150, 182, 91])
get_diag = stripe(some_matrix)

Я получаю эту ошибку: ValueError: too many values to unpack (expected 2)

Если я просто попытаюсь пропустить первое измерение, выполнив x, i, j = a.size(), Я получаю это: RuntimeError: invalid argument 1: expected a matrix or a vector at

Я все еще на PyTorch 0.3.1. Любая помощь приветствуется!

Ответы [ 2 ]

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

Вот способ сделать это без использования stack и unbind, вычислив диагональную полосу непосредственно в матрице пакета:

def batch_stripe(a):
    b, i, j = a.size()
    assert i > j
    b_s, k, l = a.stride()
    return torch.as_strided(a, (b, i - j, j), (b_s, k, k+1))

Для получения дополнительной информации обратитесь к: https://discuss.pytorch.org/t/optimizing-diagonal-stripe-code/17777/5

0 голосов
/ 30 апреля 2018

Вы можете отобразить функцию полосы по первому измерению вашего тензора, используя torch.unbind как

In [1]: import torch

In [2]: def strip(a):
   ...:     i, j = a.size()
   ...:     assert(i >= j)
   ...:     out = torch.zeros((i - j + 1, j))
   ...:     for diag in range(0, i - j + 1):
   ...:         out[diag] = torch.diag(a, -diag)
   ...:     return out
   ...: 
   ...: 

In [3]: a = torch.randn((182, 91)).cuda()

In [5]: output = strip(a)

In [6]: output.size()
Out[6]: torch.Size([92, 91])

In [7]: a = torch.randn((150, 182, 91))

In [8]: output = list(map(strip, torch.unbind(a, 0)))

In [9]: output = torch.stack(output, 0)

In [10]: output.size()
Out[10]: torch.Size([150, 92, 91])
...