蟒蛇:矢量化计算实施使用的迭代方法

0

的问题

我试图实施一些计算,但是我不知道如何矢量化我的代码而不使用循环。

让我解释一下:我有一个矩阵 M[N,C]01. 另一个矩阵 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,:]>)

这里是我的迭代方法:

    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, mc (在小写,以避免含糊不清),可以用以改变形状的所有你的张量来 (n, m, c)通过复制他们的价值超过缺少的层面(例如 M(m, c) 变得 M(n, m, c)).

但是,你可以跳过明确复制和使用广播,使它足以unsqueeze缺少的层面(例如 M(m, c) 变得 M(1, m, c).

鉴于这些考虑,矢量化的代码变得如下

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ý
..................................................................................................................