Forma eficiente de enviar un tensor de datos a través de una función sin un bucle.
Tengo una red neuronal (mi función):
import torch
import torch.nn as nn
import torch.optim as optim
softplus = torch.nn.Softplus()
class Model(nn.Module):
def __init__(self):
super(Model, self).__init__()
self.fc1 = nn.Linear(4, 10)
self.fc2 = nn.Linear(10, 10)
self.fc3 = nn.Linear(10, 1)
def forward(self, x):
x = torch.relu(self.fc1(x))
x = torch.relu(self.fc2(x))
x = softplus(self.fc3(x))
return x
net = Model()
También tengo datos en forma de un tensor grande (ten en cuenta que aquí hay un ejemplo pequeño) que se genera sobre la marcha (es decir, en cada época obtengo un nuevo tensor):
for epoch in range(10):
data = torch.rand(5,3)
Estos datos deben enviarse a la red. La dificultad es que mi función debe tomar 4 valores como entrada, donde 3 de ellos son cada uno de los tensores en el tensor de datos (5×3 para 5 triples en este ejemplo), y la cuarta entrada es la suma de las salidas anteriores de la función. El primer triple se combina con un valor inicial de 0:
init_value = torch.tensor([0])
torch.cat((data[0],init_value))
Por lo tanto, para mi primera entrada, concateno el init_value
y lo envío a la función. Si esta función produce una salida de valor 1.2
, necesito enviar el siguiente triple a la red como [x, y, z, 0+1.2]
, donde x, y, z
es el segundo triple del tensor de datos. Según aquí, parece que torch.cat
funciona con la operación backward
que se necesita y por eso lo estoy usando.
¿Hay alguna manera eficiente de hacer esto? Actualmente, lo que estoy haciendo es usar un bucle for
, enviando cada tensor del tensor de datos a la red y concatenando la suma de los valores hasta el momento. Pero dado que este es un tensor muy grande, no es muy óptimo.
davy.ai
Una posible solución a este problema es utilizar las clases
DataLoader
yIterableDataset
de PyTorch para generar el tensor de datos sobre la marcha y enviarlo a la red neuronal.En primer lugar, podemos definir una clase personalizada
IterableDataset
que genere el tensor de datos sobre la marcha utilizando la declaraciónyield
. Para realizar un seguimiento de la suma acumulada de las salidas de la función, podemos definir una variableprev_output
que inicialmente se establece en cero.A continuación, podemos utilizar un
DataLoader
para iterar sobre los datos en lotes y enviarlos a la red neuronal para su entrenamiento.Este enfoque debería ser más eficiente que utilizar un bucle ‘for’ para iterar sobre el tensor de datos, ya que solo genera datos sobre la marcha según sea necesario y evita asignaciones de memoria innecesarias.