Python: Vectorizare Calcul Implementat folosind Abordări Iterative

0

Problema

Încerc să pună în aplicare unele calcule, dar eu nu pot da seama cum să vectorize codul meu și nu folosind bucle.

Permiteți-mi să explic: am un matrix M[N,C] fie 0 sau 1. O altă matrice Y[N,1] conțin valori de [0,C-1] (Clasa mea). O altă matrice ds[N,M] care este setul de date.

Mea ieșire este matricea de dimensiune grad[M,C] și ar trebui să fie calculat după cum urmează: voi explica pentru grad[:,0], aceeași logică pentru orice altă coloană.

Pentru fiecare rând(eșantion) în dsdacă Y[that sample] != 0 (Actuală coloana de ieșire matrice) și M[that sample, 0] > 0 atunci grad[:,0] += ds[that sample]

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

Aici este meu de abordare iterativă:

    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

Cel mai bun răspuns

1

Când ai de-a face cu trei dimensiuni n, mși c (în litere mici pentru a evita ambiguitatea), acesta poate fi util pentru a schimba forma de toate tensori să (n, m, c), prin replicarea lor valori lipsă dimensiune (de exemplu, M(m, c) devine M(n, m, c)).

Cu toate acestea, puteți sări peste explicit de replicare și de a folosi de radiodifuziune, astfel încât este suficient să unsqueeze lipsă dimensiune (de exemplu, M(m, c) devine M(1, m, c).

Având în vedere aceste considerente, vectorizare codul devine, după cum urmează

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)

Aici este un mic test pentru a verifica validitatea soluției

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

Simțiți-vă liber pentru a testa pe alte cazuri la fel de bine!

2021-11-24 12:14:50

Vă mulțumesc foarte mult!
sagi

În alte limbi

Această pagină este în alte limbi

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