Python:벡터화 계산을 사용하여 구현한 반복적인 접근 방식

0

질문

나를 구현하기 위해 노력하고 몇 가지 계산이지만,수정하는 방법을 자동화 나의 코드를 사용하지 않습니다.

게 설명하십시오:나는 매트릭스 M[N,C] 의 중 01. 또 다른 매트릭스 Y[N,1] 을 포함하는 값의 [0,C-1] (나 클래스). 또 다른 매트릭스 ds[N,M] 는 내용합니다.

출력 매트릭스의 크기 grad[M,C] 해야 합 계산하는 다음과 같다:내가에 대한 설명 grad[:,0]같은 논리를 다른 어떤 열입니다.

각 행에 대해(예제)에 ds는 경우 Y[that sample] != 0 (현재 열의 행렬 출력)고 M[that sample, 0] > 0 다음 grad[:,0] += ds[that sample]

는 경우 Y[that sample] == 0다음 grad[:,0] -= (ds[that sample] * <Num of non zeros in M[that sample,:]>)

여기에는 나의 반복적인 접근 방식:

    for i in range(M.size(dim=1)):
        for j in range(ds.size(dim=0)):
            if y[j] == i:
                grad[:,i] = grad[:,i] - (ds[j,:].T * sum(M[j,:]))
            else:
                if M[j,i] > 0:
                    grad[:,i] = grad[:,i] + ds[j,:].T 
python pytorch vectorization
2021-11-23 15:58:15
1

최고의 응답

1

때문에 당신과 함께 다루고 있는 세 가지 크기 n, mc (소문자로 혼란을 피하기 위해),유용할 수 있습의 형상을 변경하는 귀하의 모든 텐서해 (n, m, c),복제하여 그들의 값 없는 차원(예를들면 M(m, c)M(n, m, c)).

그러나,당신은 건너뛸 수 있는 명시적 복제 및 사용방송,그래서 그것은 충분한 unsqueeze 없는 차원(예를들면 M(m, c)M(1, m, c).

이러한 점을 고려면 오류 코드가 다음과 같이

cond = y.unsqueeze(2) == torch.arange(M.size(dim=1)).unsqueeze(0)
pos = ds.unsqueeze(2) * M.unsqueeze(1) * cond
neg = ds.unsqueeze(2) * M.unsqueeze(1).sum(dim=0, keepdim=True) * ~cond
grad += (pos - neg).sum(dim=0)

여기에 작은 시험의 유효성을 확인할 수 있는 솔루션

import torch

n, m, c = 11, 5, 7

y = torch.randint(c, size=(n, 1))
ds = torch.rand(n, m)
M = torch.randint(2, size=(n, c))
grad = torch.rand(m, c)


def slow_grad(y, ds, M, grad):
    for i in range(M.size(dim=1)):
        for j in range(ds.size(dim=0)):
            if y[j] == i:
                grad[:,i] = grad[:,i] - (ds[j,:].T * sum(M[j,:]))
            else:
                if M[j,i] > 0:
                    grad[:,i] = grad[:,i] + ds[j,:].T
    return grad


def fast_grad(y, ds, M, grad):
    cond = y.unsqueeze(2) == torch.arange(M.size(dim=1)).unsqueeze(0)
    pos = ds.unsqueeze(2) * M.unsqueeze(1) * cond
    neg = ds.unsqueeze(2) * M.unsqueeze(1).sum(dim=0, keepdim=True) * ~cond
    grad += (pos - neg).sum(dim=0)
    return grad
  
# Assert equality of all elements function outputs, throws an exception if false
assert torch.all(slow_grad(y, ds, M, grad) == fast_grad(y, ds, M, grad))

무료 테스트뿐만 아니라 다른 경우에!

2021-11-24 12:14:50

대단히 감사합니다!
sagi

다른 언어로

이 페이지는 다른 언어로되어 있습니다

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................