Pytorch: Pesos que no cambian durante el entrenamiento

Básicamente la misma pregunta que esta aquí, que nunca fue contestada: ¿Por qué los primeros pesos de capa convolutiva no cambian durante el entrenamiento?

Sólo quiero ver los pesos de mis capas convolutivas mientras cambian durante el entrenamiento. ¿Cómo puedo hacer esto? No importa lo que haga, los pesos parecen permanecer iguales aunque la pérdida está disminuyendo.

Estoy tratando de seguir este tutorial aquí, aunque el modelo es ligeramente diferente: https://pytorch.org/tutorials/beginner/blitz/cifar10_tutorial.html#sphx-glr-beginner-blitz-cifar10-tutorial-py

Modelo

class CNN(nn.Module):
    def __init__(self):
        super(Digit_Classifier, self).__init__()
        self.conv1 = nn.Conv2d(1,6,3)
        self.pool1 = nn.MaxPool2d(2)
        self.conv2 = nn.Conv2d(6,16,3)
        self.pool2 = nn.MaxPool2d(2)
        self.out = nn.Linear(400, 10)

    def forward(self, inputs):
        x = self.pool1(F.relu(self.conv1(inputs)))
        x = self.pool2(F.relu(self.conv2(x)))
        x = torch.flatten(x, start_dim=1)
        x = self.out(x)
        return x

Capacitación

def train(epochs=100):
    criterion = nn.CrossEntropyLoss()
    net = CNN()
    optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
    losses = []
    
    for epoch in range(epochs):  # loop over the dataset multiple times

        running_loss = 0.0
        for i, data in enumerate(trainloader, 0):
            # get the inputs; data is a list of [inputs, labels]
            inputs, labels = data

            # zero the parameter gradients
            optimizer.zero_grad()

            outputs = net(inputs)
            loss = criterion(outputs, labels)
            loss.backward()
            optimizer.step()

            running_loss += loss.item()            
            w = model.conv1._parameters['weight']
            print(w)            

            losses.append(running_loss / z)
            if i % 2000 == 1999:    # print every 2000 mini-batches
                print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 2000))
                running_loss = 0.0
    return net

Pregunta hecha hace 3 años, 4 meses, 29 días - Por rubyrogue


3 Respuestas:

  • Si usted no utiliza ningún módulo de normalización, cuanto más cerca estén los pesos a la entrada de la red, más pequeño serán los gradientes y por lo tanto los cambios serán, así que los cambios probablemente estén en los decimales que ya no se muestran en sus print() declaración. Para ver los cambios, sugeriría guardar los pesos de una iteración a la siguiente, y restarlos para mostrar la diferencia:

    ...
    w = model.conv1._parameters['weight'].detach()
    print(w-w_previous)
    w_previous = w
    ...
    

    Respondida el Dec 17, 2020 a las 20:47 - por codesculptor3f6e

    Votos positivos: 0 | Votos negativos: 0

  • El problema que estás experimentando podría deberse a una confusión en el nombre de la clase. En el código que proporcionaste, tienes una clase CNN pero al llamar al método super() estás utilizando Digit_Classifier, lo cual podría estar causando que los pesos no se actualicen durante el entrenamiento.

    Para solucionar este problema, asegúrate de utilizar el nombre correcto de la clase al llamar al método super(). En este caso, deberías reemplazar Digit_Classifier por CNN en la clase CNN.

    Aquí te dejo el código corregido del modelo:

    python
    class CNN(nn.Module):
        def __init__(self):
            super(CNN, self).__init__()
            self.conv1 = nn.Conv2d(1, 6, 3)
            self.pool1 = nn.MaxPool2d(2)
            self.conv2 = nn.Conv2d(6, 16, 3)
            self.pool2 = nn.MaxPool2d(2)
            self.out = nn.Linear(400, 10)
    
        def forward(self, inputs):
            x = self.pool1(F.relu(self.conv1(inputs)))
            x = self.pool2(F.relu(self.conv2(x)))
            x = torch.flatten(x, start_dim=1)
            x = self.out(x)
            return x
    

    Además, para visualizar los pesos de las capas convolutivas mientras cambian durante el entrenamiento, puedes imprimir los pesos dentro del bucle de entrenamiento de la siguiente manera:

    python
    for i, data in enumerate(trainloader, 0):
        

    get the inputs; data is a list of [inputs, labels]

    inputs, labels = data

    zero the parameter gradients

    optimizer.zero_grad() outputs = net(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() running_loss += loss.item()

    Print weights of conv1 layer

    w = net.conv1.weight print(w) losses.append(running_loss / z) if i % 2000 == 1999:

    print every 2000 mini-batches

    print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 2000)) running_loss = 0.0

    Al hacer estos cambios, deberías poder ver los pesos de la capa convolutiva conv1 mientras cambian durante el proceso de entrenamiento. ¡Espero que esta corrección te ayude a resolver tu problema!

    Respondida el Dec 18, 2020 a las 20:47 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Existen algunas razones potenciales por las que los pesos de tu primera capa convolucional pueden no estar cambiando durante el entrenamiento:

    Sesgo de inicialización: La forma en que inicializas los pesos de la red puede influir en su comportamiento durante el entrenamiento. Asegúrate de que los pesos se inicialicen con una distribución adecuada (por ejemplo, distribución normal o uniforme) para evitar que se atasquen en valores específicos.

    Tasa de aprendizaje demasiado baja: Si la tasa de aprendizaje es demasiado baja, los pesos pueden tardar mucho en actualizarse y es posible que no cambien significativamente durante un número limitado de épocas. Intenta aumentar la tasa de aprendizaje y observa si eso hace alguna diferencia.

    Regularización insuficiente: La regularización, como la eliminación o el abandono, ayuda a prevenir el sobreajuste y puede facilitar la actualización de los pesos. Considera agregar regularización a tu modelo e intenta nuevamente.

    Gradientes de desvanecimiento: Si la red es muy profunda, los gradientes de las capas iniciales pueden volverse muy pequeños y dificultar la actualización de los pesos. Intenta usar una red menos profunda o técnicas de normalización de gradientes para mitigar este problema.

    Error en el código:* Revisa cuidadosamente tu código para asegurarte de que los pesos de la primera capa convolucional se actualicen correctamente. Verifica que la red esté configurada en modo de entrenamiento y que el optimizador esté actualizando los pesos correctos.

    Aquí hay un fragmento de código modificado que imprime los pesos de la primera capa convolucional después de cada iteración de entrenamiento:

    python
    def train(epochs=100):
        criterion = nn.CrossEntropyLoss()
        net = CNN()
        optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
        losses = []
    
        for epoch in range(epochs):  

    loop over the dataset multiple times

    running_loss = 0.0 for i, data in enumerate(trainloader, 0):

    get the inputs; data is a list of [inputs, labels]

    inputs, labels = data

    zero the parameter gradients

    optimizer.zero_grad() outputs = net(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() running_loss += loss.item() w = model.conv1._parameters['weight'] print(w) losses.append(running_loss / z) if i % 2000 == 1999:

    print every 2000 mini-batches

    print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 2000)) running_loss = 0.0 return net

    Ejecuta este código y observa si los pesos de la primera capa convolucional están cambiando. Si aún no lo están, considera las sugerencias anteriores para abordar posibles problemas.

    Respondida el Dec 18, 2020 a las 20:57 - por Gemini

    Votos positivos: 0 | Votos negativos: 0