Python: Векторизация obliczenia realizowane z wykorzystaniem podejścia итеративного

0

Pytanie

Próbuję wykonać pewne obliczenia, ale nie mogę zrozumieć, jak векторизовать swój kod i nie używać cykle.

Pozwól mi wyjaśnić: mam matryca M[N,C] z każdego 0 lub 1. Jeszcze jedna matryca Y[N,1] zawierające wartości [0,C-1] (Moje zajęcia). Jeszcze jedna matryca ds[N,M] to mój zestaw danych.

Moja wyjściowa macierz ma rozmiar grad[M,C] i powinno być obliczone w następujący sposób: wyjaśnię dla grad[:,0]ta sama logika dla innej kolumny.

Dla każdego wiersza(próbki) w dsjeśli Y[that sample] != 0 (Kolumna wyjściowej matrycy) i M[that sample, 0] > 0 wtedy grad[:,0] += ds[that sample]

Jeśli Y[that sample] == 0wtedy grad[:,0] -= (ds[that sample] * <Num of non zeros in M[that sample,:]>)

Oto mój iteracyjne podejście:

    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

Najlepsza odpowiedź

1

Ponieważ masz do czynienia z trzema miarami n, mi c (małymi literami, aby uniknąć dwuznaczności), może być przydatne zmienić kształt wszystkich тензоров na (n, m, c)poprzez replikacji ich wartości zaginionego pomiaru (np. M(m, c) staje się M(n, m, c)).

Można jednak pominąć sama replikacja i korzystać z emisji transmisję, więc wystarczy anulować żądanie brakujące pomiaru (np. M(m, c) staje się M(1, m, c).

Biorąc pod uwagę te względy, векторизация twojego kodu staje się następnej

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)

Oto mały test, aby sprawdzić poprawność rozwiązania

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))

Zapraszam do testowania i w innych przypadkach!

2021-11-24 12:14:50

Dziękuję bardzo!
sagi

W innych językach

Ta strona jest w innych językach

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