Python: Vectorize Výpočet Realizován pomocí Iterativní Přístup

0

Otázka

Snažím se realizovat nějaký výpočet, ale nemůžu přijít na to, jak vectorize můj kód, a ne pomocí smyčky.

Dovolte mi vysvětlit: mám matrix M[N,C] buď 0 nebo 1. Další matice Y[N,1] obsahující hodnoty [0,C-1] (Mé třídy). Další matice ds[N,M] což je můj dataset.

Můj výstup je matice velikosti grad[M,C] a měla by být vypočtena následovně: já ti to vysvětlím pro grad[:,0], stejnou logiku pro jakýkoli jiný sloupec.

Pro každý řádek(vzorek), v dspokud Y[that sample] != 0 (Aktuální sloupec výstupní matice) a M[that sample, 0] > 0 pak grad[:,0] += ds[that sample]

Pokud Y[that sample] == 0pak grad[:,0] -= (ds[that sample] * <Num of non zeros in M[that sample,:]>)

Tady je můj iterativní přístup:

    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

Nejlepší odpověď

1

Od té doby se zabýváme třemi rozměry n, ma c (v malými písmeny, aby se zabránilo dvojznačnosti), může být užitečné změnit tvar všechny své tenzory na (n, m, c)tím , kopírující jejich hodnoty za chybějící rozměr (např. M(m, c) stává M(n, m, c)).

Nicméně, můžete přeskočit explicitní replikace a používat vysílání, tak to je dostačující, aby unsqueeze chybějící rozměr (např. M(m, c) stává M(1, m, c).

S ohledem na tyto úvahy, vektorizace váš kód stane takto

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)

Tady je malý test, k ověření platnosti řešení

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

Neváhejte vyzkoušet i jiné případy, jak dobře!

2021-11-24 12:14:50

Děkuji moc!!!
sagi

V jiných jazycích

Tato stránka je v jiných jazycích

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