Python: Yinelemeli Yaklaşım Kullanılarak Uygulanan Hesaplamayı Vektörize Etme

0

Soru

Bazı hesaplamaları uygulamaya çalışıyorum, ancak kodumu nasıl vektörize edeceğimi ve döngüler kullanmayacağımı anlayamıyorum.

Açıklamama izin verin: Bir matrisim var M[N,C] ikisinden de 0 veya 1. Başka bir matris Y[N,1] değerleri içeren [0,C-1] (Derslerim). Başka bir matris ds[N,M] bu benim veri kümem.

Çıktı matrisim boyuttadır grad[M,C] ve aşağıdaki gibi hesaplanmalıdır: Açıklayacağım grad[:,0] başka bir sütun için aynı mantık.

Her satır için(örnek) ds, eğer Y[that sample] != 0 (Çıkış matrisinin geçerli sütunu) ve M[that sample, 0] > 0 , sonraları grad[:,0] += ds[that sample]

Eğer Y[that sample] == 0, sonraları grad[:,0] -= (ds[that sample] * <Num of non zeros in M[that sample,:]>)

İşte benim yinelemeli yaklaşımım:

    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

En iyi cevabı

1

Üç boyutla uğraştığınız için n, m, ve c (belirsizliği önlemek için küçük harfle), tüm tensörlerinizin şeklini değiştirmek yararlı olabilir (n, m, c) değerlerini eksik boyut üzerinden çoğaltarak (örn. M(m, c) oluyor M(n, m, c)).

Bununla birlikte, açık çoğaltmayı atlayabilir ve yayını kullanabilirsiniz, bu nedenle eksik boyutu çözmek yeterlidir (örn. M(m, c) oluyor M(1, m, c).

Bu hususlar göz önüne alındığında, kodunuzun vektörizasyonu aşağıdaki gibi olur

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)

İşte çözümün geçerliliğini kontrol etmek için küçük bir test

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

Diğer durumlarda da test etmekten çekinmeyin!

2021-11-24 12:14:50

Çok teşekkürler!
sagi

Diğer dillerde

Bu sayfa diğer dillerde

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