ปลั๊กอินสำหรับไพธอน:Vectorize การคำนวณการจัดเตรียมไว้ใช้ Iterative เข้าใกล้

0

คำถาม

ฉันพยายามที่จะดำเนิการคำนวณบางอย่างแต่ฉันไม่สามารถหาวิธีที่จะ vectorize ของรหัสและไม่ใช่โดยใช้บางอย่าง.

ปล่อยให้ฉันอธิบาย:ฉันมีเมตริกซ์ M[N,C] ของมือ 0 หรือ 1. อีเมตริกซ์ Y[N,1] บรรจุค่าของ [0,C-1] (ของฉันเรียน). อีเมตริกซ์ ds[N,M] ซึ่งเป็นวันที่ของฉัน.

ฉันส่งออกเมตริกซ์เป็นของขนาด grad[M,C] และควรจะถูกคำนวนที่ติดตาม:ฉันจะอธิบายสำหรับ grad[:,0]เหมือนกันตรรกะสำหรับอื่นวนคอลัมน์

สำหรับแต่ละแถวด้ว(ตัวอย่าง)ใน dsถ้า Y[that sample] != 0 (ปัจจุบันคอลัมน์ของการแสดงผลหน้าจอเมตริกซ์ว่าง)และ M[that sample, 0] > 0 แล้ว grad[:,0] += ds[that sample]

ถ้า Y[that sample] == 0แล้ว grad[:,0] -= (ds[that sample] * <Num of non zeros in M[that sample,:]>)

นี่คือของฉัน iterative เข้ามา:

    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

คำตอบที่ดีที่สุด

1

ตั้งแต่คุณกำลังรับมือกับสามมิติ n, mแล้ว c (อยู่ในตัวอักษรตัวพิมพ์เล็กจะหลีกเลี่ยง ambiguity),มันสามารถเป็นประโยชน์เพื่อเปลี่ยนรูปร่างของของคุณ tensors ต้อง (n, m, c)ด้วยแหละคำตของค่าของที่หายตัวไปมิติ(e.g. M(m, c) กลายเป็น M(n, m, c)).

อย่างไรก็ตามคุณสามารถข้ามเรื่อง explicit replication และใช้ออกอากาศดังนั้นมันเป็นเพียงพอที่จะ unsqueeze ที่หายไปในมิติ(e.g. M(m, c) กลายเป็น M(1, m, c).

ให้พวก considerations ที่ vectorization ของรหัสของคุณกลายเป็นตาม

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)

นี่เป็นเรื่องเล็กทดสอบอการตรวจสอบการตรวจสอบของทางออก

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

รู้สึกอิสระที่จะทดสอบในคดีอื่นเช่นกัน!

2021-11-24 12:14:50

ขอบคุณมากครับ!
sagi

ในภาษาอื่นๆ

หน้านี้อยู่ในภาษาอื่นๆ

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