Pytorch resnet con cero pérdida

Estoy entrenando un modelo Pytorch Resnet para segmentación de imágenes. Tengo dos clases y estoy entrenando con imágenes RGB y máscaras binarias correspondientes. Mientras que mis valores de precisión son muy altos (~0.99), mis valores de pérdida para entrenamiento y validación son ceros en todas las épocas. ¿Cómo puedo solucionar este problema?

#we do the spatial transformations first, and afterwards do any color augmentations
img_transform = transforms.Compose([
    transforms.ToPILImage(),
    transforms.RandomVerticalFlip(),
    transforms.RandomHorizontalFlip(),
    transforms.RandomCrop(size=(patch_size,patch_size),pad_if_needed=True), #these need to be in a reproducible order, first affine transforms and then color
    transforms.RandomResizedCrop(size=patch_size),
    transforms.RandomRotation(180),
    transforms.ColorJitter(brightness=0, contrast=0, saturation=0, hue=.5),
    transforms.RandomGrayscale(),
    transforms.ToTensor()
    ])


mask_transform = transforms.Compose([
    transforms.ToPILImage(),
    transforms.RandomVerticalFlip(),
    transforms.RandomHorizontalFlip(),
    transforms.RandomCrop(size=(patch_size,patch_size),pad_if_needed=True), #these need to be in a reproducible order, first affine transforms and then color
    transforms.RandomResizedCrop(size=patch_size,interpolation=PIL.Image.NEAREST),
    transforms.RandomRotation(180),
    ])




dataset={}
dataLoader={}
for phase in phases: #now for each of the phases, we're creating the dataloader
                     #interestingly, given the batch size, i've not seen any improvements from using a num_workers>0
    dataset[phase]=Dataset(f"/content/{dataname}_{phase}.pytable", img_transform=img_transform , mask_transform = mask_transform ,edge_weight=edge_weight)
    dataLoader[phase]=DataLoader(dataset[phase], batch_size=batch_size, 
                                shuffle=True, num_workers=0, pin_memory=True)
    

optim = torch.optim.Adam(model.parameters()) 
nclasses = dataset["train"].numpixels.shape[1]
class_weight=dataset["train"].numpixels[1,0:2] #don't take ignored class into account here
class_weight = torch.from_numpy(1-class_weight/class_weight.sum()).type('torch.FloatTensor').to(device)

print(class_weight) #show final used weights, make sure that they're reasonable before continouing
criterion = nn.CrossEntropyLoss(weight = class_weight, ignore_index = ignore_index ,reduce=False) #reduce = False makes sure we get a 2D output instead of a 1D "summary" value


for epoch in range(num_epochs):
    #zero out epoch based performance variables 
    print('Epoch {}/{}'.format(epoch, num_epochs - 1))
    print('-' * 10)
    all_acc = {key: 0 for key in phases} 
    all_loss = {key: torch.zeros(0).to(device) for key in phases}
    cmatrix = {key: np.zeros((2,2)) for key in phases}

    for phase in phases: #iterate through both training and validation states

        if phase == 'train':
            model.train()  # Set model to training mode
        else: #when in eval mode, we don't want parameters to be updated
            model.eval()   # Set model to evaluate mode
        running_loss = 0.0
        running_corrects = 0
        for ii , (X, y, y_weight) in enumerate(dataLoader[phase]): #for each of the batches
            optim.zero_grad()
            X = X.to(device)  # [Nbatch, 3, H, W]
            y_weight = y_weight.type('torch.FloatTensor').to(device)
            y = y.type('torch.LongTensor').to(device)  # [Nbatch, H, W] with class indices (0, 1)
            with torch.set_grad_enabled(phase == 'train'): #dynamically set gradient computation, in case of validation, this isn't needed
                                                            #disabling is good practice and improves inference time

                prediction = model_ft(X)  # [N, Nclass]
                y = y[:, 0,0]
                loss = criterion(prediction, y)
                print(loss)
                _, preds = torch.max(X, 1)
                preds = preds[:,0,0]
                if phase=="train": #in case we're in train mode, need to do back propogation
                    
                    loss.mean().backward()
                    optim.step()
                

                

            running_loss += loss.data[0]
            running_corrects += torch.sum(preds == y)
        epoch_loss = running_loss / len(dataLoader[phase].dataset)
        epoch_acc = running_corrects.double() / len(dataLoader[phase].dataset)

        print('{} Loss: {:.4f} Acc: {:.4f}'.format(phase, epoch_loss, epoch_acc))

        # deep copy the model
        if phase == 'val' and epoch_acc > best_acc:
           best_acc = epoch_acc
           best_model_wts = copy.deepcopy(model.state_dict())
        if phase == 'val':
           val_acc_history.append(epoch_acc)

    print()

Pregunta hecha hace 3 años, 4 meses, 27 días - Por codergeek24


2 Respuestas:

  • El hecho de que tu pérdida sea cero en todas las épocas puede indicar que hay un error en la forma en que estás calculando la pérdida en tu código. Aquí hay algunas sugerencias que podrían ayudarte a solucionar este problema:

    • Revisa cómo estás calculando la pérdida en tu código. En la línea `loss = criterion(prediction, y)`, probablemente estás pasando los datos incorrectamente o usando el tensor incorrecto para calcular la pérdida. Asegúrate de que estás pasando los valores correctos al criterio de pérdida.
    • Verifica que estés calculando correctamente la pérdida promedio en cada época. En la línea `epoch_loss = running_loss / len(dataLoader[phase].dataset)`, asegúrate de que estás dividiendo la suma total de pérdidas por el tamaño total del conjunto de datos.
    • Asegúrate de que estás utilizando las predicciones correctas para calcular la precisión. En la línea `_, preds = torch.max(X, 1)`, estás calculando la precisión utilizando `X` en lugar de `prediction`.
    • Para asegurarte de que tu red neuronal ResNet se está entrenando correctamente, puedes verificar cómo se actualizan los pesos del modelo en cada época. Puedes imprimir los valores de los pesos antes y después de la actualización para asegurarte de que están cambiando.

    Espero que estas sugerencias te ayuden a identificar y solucionar el problema con la pérdida cero en tu modelo ResNet de PyTorch. ¡Déjame saber si tienes alguna otra pregunta o si necesitas más ayuda!

    Respondida el Dec 20, 2020 a las 14:29 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Te sugiero que verifiques los siguientes puntos para solucionar el problema de pérdida cero en tu entrenamiento de segmentación de imágenes con Pytorch Resnet:

    • Verifica tus etiquetas de máscara: Asegúrate de que tus etiquetas de máscara binarias sean correctas y que no haya valores perdidos o vacíos. Cualquier etiqueta de máscara faltante o incorrecta puede provocar que la pérdida sea cero.
    • Comprueba tu función de pérdida: Verifica que utilizas la función de pérdida correcta para tu tarea de segmentación. En este caso, deberías utilizar `nn.CrossEntropyLoss` o `nn.BCEWithLogitsLoss`, según el tipo de etiquetas de máscara que tengas (clases o binarias).
    • Inspecciona tus datos: Visualiza algunos ejemplos de tus datos de entrenamiento para asegurarte de que los datos sean válidos y de que las máscaras estén alineadas correctamente con las imágenes.
    • Revisa tu código de entrenamiento: Asegúrate de que estás calculando y propagando la pérdida correctamente en tu código de entrenamiento. Verifica que la salida de tu modelo se está comparando con las etiquetas de máscara correctas y que la pérdida se está acumulando y propagando mediante la optimización.
    • Verifica tu conjunto de datos: Asegúrate de que tu conjunto de datos contenga suficientes datos para entrenar el modelo de manera efectiva. Un conjunto de datos demasiado pequeño o desequilibrado puede provocar problemas de sobreajuste o subajuste, lo que puede resultar en una pérdida cero.
    • Ajusta los hiperparámetros: Experimenta con diferentes hiperparámetros, como la tasa de aprendizaje, el tamaño del lote y el número de épocas. Ajustar estos parámetros puede mejorar el rendimiento del entrenamiento y reducir la pérdida.
    • Intenta con un modelo más simple: Para descartar cualquier problema con la arquitectura del modelo, prueba con un modelo Resnet más simple o un modelo de segmentación diferente. Esto puede ayudarte a identificar si el problema está en el modelo o en tu configuración de entrenamiento.

    Si después de verificar estos puntos sigues teniendo problemas con una pérdida cero, proporciona más detalles sobre tu código, datos y configuración de entrenamiento para que podamos ayudarte mejor.

    Respondida el Dec 20, 2020 a las 14:33 - por Gemini

    Votos positivos: 0 | Votos negativos: 0