Python: Vectorización de Cálculo Implementado utilizando el Enfoque Iterativo

0

Pregunta

Estoy tratando de implementar algunos de cálculo, pero no puedo entender cómo vectorizar mi código y no mediante bucles.

Me explico: tengo una matriz M[N,C] de cualquiera de las 0 o 1. Por otra matriz Y[N,1] contiene los valores de [0,C-1] (Mis clases). Por otra matriz ds[N,M] cual es mi conjunto de datos.

Mi salida de la matriz es de tamaño grad[M,C] y debe ser calculado como sigue: voy a explicar para grad[:,0], la lógica misma de cualquier otra columna.

Para cada fila(de la muestra) en dssi Y[that sample] != 0 (La columna actual de salida de la matriz) y M[that sample, 0] > 0 , a continuación, grad[:,0] += ds[that sample]

Si Y[that sample] == 0, a continuación, grad[:,0] -= (ds[that sample] * <Num of non zeros in M[that sample,:]>)

Aquí está mi enfoque iterativo:

    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

Mejor respuesta

1

Ya que se trata de tres dimensiones n, my c (en minúsculas para evitar la ambigüedad), puede ser útil para cambiar la forma de todos sus tensores para (n, m, c)mediante la replicación de sus valores sobre la dimensión que falta (por ejemplo, M(m, c) se convierte en M(n, m, c)).

Sin embargo, usted puede saltar el explícito de replicación y el uso de la radiodifusión, por lo que es suficiente para que estire la dimensión que falta (por ejemplo, M(m, c) se convierte en M(1, m, c).

Teniendo en cuenta estas consideraciones, la vectorización de su código se hace de la siguiente manera

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)

He aquí una pequeña prueba para comprobar la validez de la solución

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

Siéntase libre de probar en otros casos así!

2021-11-24 12:14:50

Muchas gracias!
sagi

En otros idiomas

Esta página está en otros idiomas

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