Pytorch, избавьтесь от цикла for при добавлении перестановки одного вектора в элементы матрицы?
Я пытаюсь реализовать эту статью и придерживаюсь этого простого шага. Хотя это связано с вниманием, я застрял в том, как реализовать перестановку вектора, добавленного в матрицу, без использования циклов 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)])
Ответы
Я не мог понять, что 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
.