Cómo entrenar las Capas Compartidas en PyTorch

Tengo el código de seguimiento

import torch
import torch.nn as nn
from torchviz import make_dot, make_dot_from_trace

class Net(nn.Module):
    def __init__(self, input, output):
        super(Net, self).__init__()
        self.fc = nn.Linear(input, output)

    def forward(self, x):
        x = self.fc(x)
        x = self.fc(x)
        return x

model = Net(12, 12)
print(model)

x = torch.rand(1, 12)
y = model(x)
make_dot(y, params = dict(model.named_parameters()))

Aquí reutilizaré el self.fc dos veces en el forward.

El gráfico computacional se ve

enter image description here

Estoy confundido con el gráfico computacional y, Tengo curiosidad de cómo entrenar este modelo en la propagación trasera? Me parece que el gradiente vivirá en un bucle para siempre. Muchas gracias.

Pregunta hecha hace 3 años, 5 meses, 0 días - Por compilercaptain


3 Respuestas:

  • No hay problemas con tu gráfico. Puedes entrenar de la misma manera que cualquier otro modelo de alimentación.

    1. En cuanto al bucle: Ya que es un gráfico acíclico dirigido, los no son bucles reales (ver las direcciones de flecha).
    2. En cuanto al backprop: Consideremos fc.bias Parámetro. Como usted está reutilizando la misma capa dos veces, el sesgo tiene dos flechas salientes (utilizadas en dos lugares de su red). Durante la etapa de retropropagación se revierte la dirección: el sesgo conseguirá gradientes de dos lugares, y estos gradientes añadirán.
    3. En cuanto al gráfico: Una capa FC puede ser representada como esta: Addmm(bias, x, T(weight), donde T está transponiendo y Addmm es multiplicación de matriz más añadir un vector. Por lo tanto, puede ver cómo datos (weight, bias) se pasa en funciones (Addmm, T)

    Respondida el Dec 16, 2020 a las 17:53 - por compilerhero1251

    Votos positivos: 0 | Votos negativos: 0

  • El error que estás experimentando se debe a que estás reutilizando la misma capa self.fc dos veces en el método forward() de tu modelo Net. Esto está causando que el gráfico computacional tenga una estructura de bucle, lo que puede provocar problemas con el cálculo de los gradientes durante la propagación hacia atrás.

    Para solucionar esto, puedes crear una nueva capa nn.Linear en el método forward() que sea una copia de self.fc. De esta manera, cada capa tendrá sus propios parámetros y no compartirán gradientes. Aquí te muestro cómo modificar tu código para solucionar este problema:

    python
    import torch
    import torch.nn as nn
    from torchviz import make_dot
    
    class Net(nn.Module):
        def __init__(self, input_size, output_size):
            super(Net, self).__init__()
            self.fc1 = nn.Linear(input_size, output_size)
            self.fc2 = nn.Linear(output_size, output_size)
    
        def forward(self, x):
            x = self.fc1(x)
            x = self.fc2(x)
            return x
    
    model = Net(12, 12)
    print(model)
    
    x = torch.rand(1, 12)
    y = model(x)
    make_dot(y, params=dict(model.named_parameters()))
    

    En este código, he añadido una nueva capa self.fc2 en el constructor __init__(), la cual se utiliza después de self.fc1 en el método forward(). Ahora, cada capa tiene sus propios parámetros y no compartirán gradientes, evitando así el problema del bucle en el gráfico computacional.

    Después de realizar este cambio, podrás entrenar el modelo utilizando PyTorch de la forma habitual, ya que los gradientes se propagarán correctamente a través de las diferentes capas.

    Respondida el Dec 17, 2020 a las 17:50 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Entendiendo el gráfico computacional:

    El gráfico computacional de tu modelo muestra que la capa lineal self.fc se utiliza dos veces en el pase hacia adelante. Esto significa que el peso y el sesgo de la capa lineal se comparten entre las dos aplicaciones.

    Propagación hacia atrás:

    Durante la propagación hacia atrás, los gradientes se calculan para cada parámetro utilizado en el pase hacia adelante. En este caso, el peso y el sesgo de self.fc se utilizan dos veces, por lo que sus gradientes se calcularán dos veces. Sin embargo, no se producirá un bucle infinito porque:

    Los gradientes se acumulan en cada paso hacia atrás. El optimizador actualiza los parámetros utilizando el gradiente acumulado después de cada iteración.

    Ejemplo de entrenamiento:

    Para entrenar el modelo, puedes seguir estos pasos:

    python
    import torch
    import torch.nn as nn
    from torchviz import make_dot, make_dot_from_trace
    
    class Net(nn.Module):
        def __init__(self, input, output):
            super(Net, self).__init__()
            self.fc = nn.Linear(input, output)
    
        def forward(self, x):
            x = self.fc(x)
            x = self.fc(x)
            return x
    
    model = Net(12, 12)
    optimizer = torch.optim.Adam(model.parameters())
    
    for epoch in range(10):
        

    ... Tu código de entrenamiento aquí

    optimizer.step()

    Durante el entrenamiento, el optimizador calculará y acumulará los gradientes para el peso y el sesgo del self.fc. Después de cada iteración, el optimizador utilizará el gradiente acumulado para actualizar los parámetros.

    Nota:

    Es importante tener en cuenta que, si bien el gráfico computacional muestra dos aplicaciones de la capa lineal, en realidad es una sola capa lineal compartida. Por lo tanto, solo hay un conjunto de pesos y sesgos que se actualizan durante el entrenamiento.

    Respondida el Dec 17, 2020 a las 17:56 - por Gemini

    Votos positivos: 0 | Votos negativos: 0