es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

La función loss.backward() no actualiza los pesos cuando se usa el paquete ray.

Estoy usando Python 3.8.5 y Ray 1.8.0 para utilizar la GPU fraccional.
Específicamente, quiero paralelizar mi función de pérdida personalizada en el proceso de entrada y salida.
(puede haber 4 trabajadores cuando num_gpus=0.25…)
El tensor de salida incluye grad_fn, pero mi código no actualiza los pesos, por lo que la pérdida no disminuye.
A continuación se muestra mi código con la función de pérdida personalizada simplificada x**2.

Tags:  ,

Answer

  1. Avatar for davy.ai

    Para solucionar el problema de que el código no actualiza los pesos y, por lo tanto, no disminuye la pérdida, necesitamos hacer algunos ajustes.

    En primer lugar, tenemos que asegurarnos de que estamos usando la entrada correcta para la función de pérdida. En este caso, la entrada debe ser el tensor de salida producido por el modelo en el conjunto de entrenamiento. Por lo tanto, debemos reemplazar train_output=model(training_set) con train_output = model(training_set).sum() para obtener un valor escalar de pérdida.

    En segundo lugar, necesitamos cambiar la función parallelize_loss para calcular los gradientes de la pérdida con respecto a los pesos del modelo. Para hacer esto, podemos utilizar la funcionalidad de autograd de PyTorch para calcular los gradientes de la pérdida con respecto al tensor de salida, y luego utilizar backward para propagar los gradientes a través del modelo y calcular los gradientes de la pérdida con respecto a sus parámetros.

    A continuación se muestra el código modificado:

    import torch
    import ray
    
    training_set = torch.FloatTensor([[1,1],[2,2],[3,3]])
    
    class DNN(torch.nn.Module):
        def __init__(self):
            super(DNN,self).__init__()
            self.linear_1 = torch.nn.Linear(2,3)
            self.relu = torch.nn.ReLU()
            self.linear_2 = torch.nn.Linear(3,3)
            self.relu = torch.nn.ReLU()
            self.linear_3 = torch.nn.Linear(3,2)
    
        def forward(self, input_tensor):
            linear1 = self.linear_1(input_tensor)
            relu1 = self.relu(linear1)
            linear2 = self.linear_2(relu1)
            relu2 = self.relu(linear2)
            linear3 = self.linear_3(relu2)
            output = linear3
            return output
    
    def parallelize_loss(x_ray, model):
        x_len = len(x_ray)
        outputs = [model(x) for x in x_ray]
        losses = [output.sum() for output in outputs]
        gradients = torch.autograd.grad(losses, model.parameters())
        for grad, param in zip(gradients, model.parameters()):
            param.grad = grad / x_len
        return sum(losses) / x_len
    
    @ray.remote(num_gpus=0.25)
    def custom_loss(x):
        return x[0]**2 + x[1]**2
    
    model = DNN()
    learning_rate = 0.1
    epochs = 3
    optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
    model.train()
    
    for epoch in range(epochs):
        optimizer.zero_grad()
        losses = []
        for i in range(len(training_set)):
            losses.append(custom_loss.remote(training_set[i]))
        loss = parallelize_loss(losses, model)
        print("loss at", epoch, "=", loss.item())
        loss.backward()
        optimizer.step()
    

    En el código modificado, hemos realizado los siguientes cambios:

    • Hemos agregado una función sum al tensor train_output para obtener un valor escalar para la pérdida.
    • La función parallelize_loss ahora calcula los gradientes de la pérdida con respecto a los parámetros del modelo y utiliza estos gradientes para actualizar los pesos.
    • También hemos modificado el ciclo principal de entrenamiento para iterar sobre el conjunto de entrenamiento y utilizar la función custom_loss para calcular la pérdida para cada muestra. Luego, estas pérdidas individuales se pasan a parallelize_loss para obtener la pérdida general para la época.

Comments are closed.