Python: Vectorize di Calcolo Implementato utilizzando Approccio Iterativo

0

Domanda

Sto cercando di implementare una qualche calcolo, ma io non riesco a capire come vectorize il mio codice e non usando i loop.

Mi spiego: ho una matrice M[N,C] di 0 o 1. Un'altra matrice Y[N,1] contenente i valori di [0,C-1] (La mia classe). Un'altra matrice ds[N,M] che è il mio set di dati.

La mia uscita matrice di dimensione grad[M,C] e deve essere calcolato come di seguito: mi spiego meglio per grad[:,0], la stessa logica per qualsiasi altra colonna.

Per ogni riga(esempio) in dsse Y[that sample] != 0 (La colonna corrente di uscita di matrix) e M[that sample, 0] > 0 poi grad[:,0] += ds[that sample]

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

Qui è il mio approccio iterativo:

    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

Migliore risposta

1

Dal momento che hai a che fare con tre dimensioni n, me c (in minuscolo per evitare ambiguità), può essere utile per modificare la forma di tutti i tensori di (n, m, c), replicando i loro valori oltre la dimensione mancante (ad es. M(m, c) diventa M(n, m, c)).

Tuttavia, è possibile ignorare l'esplicita di replica e di broadcasting, pertanto è sufficiente unsqueeze la dimensione mancante (ad es. M(m, c) diventa M(1, m, c).

Alla luce di tali considerazioni, la vettorializzazione del codice diventa come segue

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)

Ecco un piccolo test per verificare la validità della soluzione

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

Sentitevi liberi di provare in altri casi, come pure!

2021-11-24 12:14:50

Vi ringrazio molto!
sagi

In altre lingue

Questa pagina è in altre lingue

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