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 벡터와 크기가 다르기 때문에 gather를 사용할 수 없습니다.

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 .