Pytorch, избавьтесь от цикла for при добавлении перестановки одного вектора в элементы матрицы?

Aug 20 2020

Я пытаюсь реализовать эту статью и придерживаюсь этого простого шага. Хотя это связано с вниманием, я застрял в том, как реализовать перестановку вектора, добавленного в матрицу, без использования циклов for.

К оценкам внимания добавлен выученный вектор смещения, теория заключается в том, что он кодирует относительное положение (ji) двух токенов, которые представляет оценка.

поэтому альфа - это матрица T x T, T зависит от пересылаемого пакета, а B - это выученный вектор смещения, длина которого должна быть фиксированной и равной 2T. Моя текущая реализация, которая, как я полагаю, делает то, что предлагает бумага:

    def __init__(...):
       ...
        self.bias = torch.nn.Parameter(torch.randn(config.n),requires_grad = True)
        stdv = 1. / math.sqrt(self.bias.data.size(0))
        self.bias.data.uniform_(-stdv, stdv)
     def forward(..)
        ...
        #n = 201  (2* max_seq_len + 1)

        B_matrix = torch.zeros(self.T, self.T) # 60 x 60
        for i in range(self.T):
          B_matrix[i] = self.bias[torch.arange(start=n//2-i, end=n//2-i+T)])]

        attention_scores = attention_scores + B_matrix.unsqueeze(0)
        # 64 x 60 x 60   
        ...

Это единственная важная часть

B_matrix = torch.zeros(self.T, self.T) # 60 x 60
        for i in range(self.T):
          B_matrix[i] = self.bias[torch.arange(start=n//2-i, end=n//2-i+T)])]

в основном пытается не использовать цикл for для просмотра каждой строки.

но я знаю, что это должно быть действительно неэффективно и дорого, когда эта модель очень большая. Я делаю явный цикл for для каждой строки, чтобы получить перестановку изученного вектора смещения.

Может ли кто-нибудь помочь мне лучшим способом, возможно, с помощью умного вещания?

Подумав об этом, мне не нужно создавать нулевую матрицу, но я все еще не могу избавиться от цикла for? и не может использовать сборку, поскольку B_matrix имеет другой размер, чем мозаичный вектор b.

functor = lambda i : bias[torch.arange(start=n//2-i, end=n//2-i+T)]
B_matrix = torch.stack([functor(i) for i in torch.arange(T)])

Ответы

2 jodag Aug 21 2020 at 12:57

Я не мог понять, что nдолжно было быть в вашем коде, но я думаю, что следующий пример использования torch.meshgridдает то, что вы ищете.

Предположим

n, m = 10, 20   # arbitrary
a = torch.randn(n, m)
b = torch.randn(n + m)

тогда

for i in range(n):
    for j in range(m):
        a[i, j] = a[i, j] + b[n - i + j]

эквивалентно

ii, jj = torch.meshgrid(torch.arange(n), torch.arange(m))
a = a + b[n - ii + jj]

хотя последняя операция неуместна, что обычно хорошо. Если вам действительно нужна операция на месте, замените ее a =на a[...] =.

Обратите внимание, что это пример индексации целочисленного массива, где мы индексируем bс использованием тензора той же формы, что и a.