Python: Vectorize de Cálculo Implementado utilizando a Abordagem Iterativa

0

Pergunta

Eu estou tentando implementar algumas cálculo, mas eu não consigo entender como vectorize meu código e não usando loops.

Deixe-me explicar: eu tenho uma matriz M[N,C] de qualquer 0 ou 1. Outra matriz Y[N,1] contendo valores de [0,C-1] (Meus cursos). Outra matriz ds[N,M] qual é o meu conjunto de dados.

A minha saída é matriz de tamanho grad[M,C] e deve ser calculado como a seguir: eu vou explicar para grad[:,0], mesmo lógica para qualquer outra coluna.

Para cada linha(exemplo) em ds, se Y[that sample] != 0 (A coluna atual de saída matrix) e M[that sample, 0] > 0 e , em seguida, grad[:,0] += ds[that sample]

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

Aqui está a minha abordagem iterativa:

    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

Melhor resposta

1

Pois você está lidando com três dimensões n, me c (em letras minúsculas para evitar ambigüidade), pode ser útil para alterar a forma de todos os seus tensores para (n, m, c), replicando seus valores sobre a falta de dimensão (por exemplo, M(m, c) torna-se M(n, m, c)).

No entanto, você pode ignorar o explícito de replicação e o uso de radiodifusão, por isso, é suficiente para unsqueeze a falta de dimensão (por exemplo, M(m, c) torna-se M(1, m, c).

Dadas estas considerações, a vetorização de o código fica da seguinte forma

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)

Aqui está um pequeno teste para verificar a validade da solução

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

Sinta-se livre para testar em outros casos bem!

2021-11-24 12:14:50

Muito obrigado!
sagi

Em outros idiomas

Esta página está em outros idiomas

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