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.

¿Cómo puedo optimizar los pesos de la capa de entrada utilizando backward en esta red neuronal simple en PyTorch cuando .grad es None?

Definí la siguiente red neuronal simple:

import torch
import torch.nn as nn

X = torch.tensor(([1, 2]), dtype=torch.float)
y = torch.tensor([1.])
learning_rate = 0.001

class Neural_Network(nn.Module):
    def __init__(self, ):
        super(Neural_Network, self).__init__()

        self.W1 = torch.nn.Parameter(torch.tensor(([1, 0], [2, 3]), dtype=torch.float, requires_grad=True))
        self.W2 = torch.nn.Parameter(torch.tensor(([2], [1]), dtype=torch.float, requires_grad=True))

    def forward(self, X):
        self.xW1 = torch.matmul(X, self.W1)
        self.h = torch.tensor([torch.tanh(self.xW1[0]), torch.tanh(self.xW1[1])])
        return torch.sigmoid(torch.matmul(self.h, self.W2))

net = Neural_Network()

for z in range(60):
    loss = (y - net(X))**2
    optim = torch.optim.SGD(net.parameters(), lr=learning_rate, momentum=0.9)
    loss = criterion(net(X), y)
    loss.backward()
    optim.step()

Puedo ejecutarlo y print(net.W1) print(net.W2) imprime

Parameter containing:
tensor([[1., 0.],
        [2., 3.]], requires_grad=True)
Parameter containing:
tensor([[2.0078],
        [1.0078]], requires_grad=True)

Así que mi problema es que parece que W1 no se está actualizando.
Cuando llamo a print(net.W1.grad) obtengo None en cada iteración, lo cual me confunde mucho.

  • Intenté definir la función en una línea así:
loss = (y - torch.sigmoid(math.tanh(x[0] * W_1[0][0] + x[1] * W_1[1][0]) * W_2[0] + math.tanh(x[0] * W_1[0][1] + x[1] * W_1[1][1]) * W_2[1])) ** 2

pero no ayudó en nada.

  • Seguro que podría codificar la derivada y todo, pero parece doloroso y pensé que backward() se puede usar en este caso.

¿Cómo puedo optimizar W1 usando backward()?

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Para optimizar W1 con backward(), necesitas modificar el código en dos lugares:

    1. Mueve la definición del optimizador fuera del bucle de entrenamiento, ya que no necesitas recrearlo cada vez.
    2. Agrega optim.zero_grad() dentro del bucle antes de loss.backward() para limpiar los gradientes de cada parámetro antes de calcular los gradientes para el lote actual de datos.

    Aquí está el código modificado:

    import torch
    import torch.nn as nn
    
    X = torch.tensor(([1, 2]), dtype=torch.float)
    y = torch.tensor([1.])
    learning_rate = 0.001
    
    class Neural_Network(nn.Module):
        def __init__(self, ):
            super(Neural_Network, self).__init__()
    
            self.W1 = torch.nn.Parameter(torch.tensor(([1, 0], [2, 3]), dtype=torch.float, requires_grad=True))
            self.W2 = torch.nn.Parameter(torch.tensor(([2], [1]), dtype=torch.float, requires_grad=True))
    
        def forward(self, X):
            self.xW1 = torch.matmul(X, self.W1)
            self.h = torch.tensor([torch.tanh(self.xW1[0]), torch.tanh(self.xW1[1])])
            return torch.sigmoid(torch.matmul(self.h, self.W2))
    
    net = Neural_Network() 
    optim = torch.optim.SGD(net.parameters(), lr=learning_rate, momentum=0.9) # definición del optimizador
    
    for z in range(60):
        optim.zero_grad() # limpiar gradientes
        loss = (y - net(X))**2
        loss.backward()
        optim.step()
    
    print(net.W1)
    print(net.W2)
    print(net.W1.grad) # debería imprimir los gradientes actualizados
    

    Ahora, cuando ejecutes print(net.W1.grad) después del entrenamiento, deberías ver los gradientes actualizados.

Comments are closed.