IMELE icon indicating copy to clipboard operation
IMELE copied to clipboard

Loss Function

Open BernhardGlueck opened this issue 2 years ago • 2 comments

Hi ! I tried integrating your model into my own pipeline, and seem to have run into some issues. I tried porting your loss implementation into proper modules, but for some reason the loss keeps going into the negative ( e.g -1.51 ) which in turn makes optimization difficult... Could you maybe take a look if i made a mistake or if there is some bug in the original code ?

import torch
import torch.nn as nn
import torch.nn.functional as F
import numpy as np


class ImeSobel(nn.Module):

    def __init__(self):
        super().__init__()
        self.edge_conv = nn.Conv2d(1, 2, kernel_size=3, stride=1, padding=1, bias=False)
        edge_kx = np.array([[1, 0, -1], [2, 0, -2], [1, 0, -1]])
        edge_ky = np.array([[1, 2, 1], [0, 0, 0], [-1, -2, -1]])
        edge_k = np.stack((edge_kx, edge_ky))

        edge_k = torch.from_numpy(edge_k).float().view(2, 1, 3, 3)
        self.edge_conv.weight = nn.Parameter(edge_k)

        for param in self.parameters():
            param.requires_grad = False

    def forward(self, x):
        out = self.edge_conv(x)
        out = out.contiguous().view(-1, 2, x.size(2), x.size(3))

        return out


class ImeLoss(nn.Module):
    def __init__(self, output_size: tuple[int, int], batch_size: int):
        super().__init__()
        self.sobel = ImeSobel()
        self.cos = nn.CosineSimilarity(dim=1, eps=0)
        self.ones = torch.ones(batch_size, 1, output_size[0], output_size[1]).float().cuda()

    def forward(self, output, depth):
        depth_grad = self.sobel(depth)
        output_grad = self.sobel(output)

        depth_grad_dx = depth_grad[:, 0, :, :].contiguous().view_as(depth)
        depth_grad_dy = depth_grad[:, 1, :, :].contiguous().view_as(depth)
        output_grad_dx = output_grad[:, 0, :, :].contiguous().view_as(depth)
        output_grad_dy = output_grad[:, 1, :, :].contiguous().view_as(depth)

        depth_normal = torch.cat((-depth_grad_dx, -depth_grad_dy, self.ones), 1)
        output_normal = torch.cat((-output_grad_dx, -output_grad_dy, self.ones), 1)
        loss_depth = torch.log(torch.abs(output - depth) + 0.5).mean()
        loss_dx = torch.log(torch.abs(output_grad_dx - depth_grad_dx) + 0.5).mean()
        loss_dy = torch.log(torch.abs(output_grad_dy - depth_grad_dy) + 0.5).mean()
        loss_normal = torch.abs(1 - self.cos(output_normal, depth_normal)).mean()

        loss = loss_depth + loss_normal + (loss_dx + loss_dy)

        return loss

BernhardGlueck avatar Apr 15 '22 03:04 BernhardGlueck

Hello there! Have you managed to acheieve any results using this model? I have been trying multiple times now to get the same results as the provided "Block0_skip_model_100", but I think there is something wrong with the model given in the repo. Any model that is trained further than epoch 1 or 2 only results in a model that produces an image where all values are the same. The predicted images have values like 0, 65534 or 2 for or all values when testing predictions. I am training using the training portion of the "osiDataset", with learning rate of 0.0001 and weight decay of 0.001. I have tried predictions and training both with and without the provided encoder model in the "pretrained_model" folder. Below you can see the tensorboard plot of the loss: bilde

TorsteinOtterlei avatar Apr 17 '22 19:04 TorsteinOtterlei

I haved used a different loss function ( either RSME or my own, very simple absolute height diff ) I get some results, but they are not very good after 50 or so epochs. However the results are definitly not all the same.

I am also trying to predict building height from satellite images, but i am using a different dataset than in the examples. I have had moderate success with a modified UNET model, and tried this model for better results, however so far this seems not to work.

BernhardGlueck avatar Apr 19 '22 01:04 BernhardGlueck