Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Loss drives below zero for self-supervised depth estimation and training fails #16

Open
rvarun7777 opened this issue Mar 9, 2020 · 12 comments

Comments

@rvarun7777
Copy link

rvarun7777 commented Mar 9, 2020

Hi, unfortunately we don't have a code release for the monocular depth estimation experiments of the paper (though that code is in TF anyways so it likely isn't what you're looking for). I believe that there are Pytorch implementations of SFMLearner on Github, and using this loss should be straightforward: just delete the existing multiscale photometric loss and the smoothness term and add in AdaptiveImageLossFunction on the full-res image with:
scale_lo=0.01
scale_init=0.01
and default settings for the rest and it should work (you may need to fiddle with the value of wavelet_scale_base).

Do you suggest any other changes apart from this? I am actually testing this :)

If you call the loss in general.py, it should never go negative. The loss produced by adaptive.py is actually a negative log-likelihood, so it can go negative depending on the value of the scale parameter. Could you kindly elaborate on this? Doesn't the -log(y) yield positive values.
Example: NLL: -ln(0.5) = 0.69
How does it drive negative or do we consider the abs(l1) finally?

After adding your loss it just drives it below 0 and the training fails.

Tested your loss in YUV space on monodepth2 project.
AdaptiveImageLossFunction((3, 640, 192), torch.float32, "cuda:0", color_space='YUV', scale_lo=0.01, scale_init=0.01)
Note: Alpha and Scale are added to the optimizers. I have skipped this part here.
These were the initial settings used. Actually, the scale of final loss of monodepth with L1 is around 0.07 to 0.02 and performs well.

Test 1
Final loss = 0.85 Adaptive Loss + 0.15 SSIM + 0.001 Smoothness
Test 2: Tried different weightage as well. This setting would fail after few epochs as well.
Final loss = 0.15 Adaptive Loss + 0.85 SSIM + 0.001 Smoothness

@rvarun7777 rvarun7777 changed the title Loss drives below 0 for self-supervised depth estimation Loss drives below zero for self-supervised depth estimation and training fails Mar 9, 2020
@jonbarron
Copy link
Owner

jonbarron commented Mar 10, 2020 via email

@rvarun7777
Copy link
Author

Thanks for the tips. Just one small note, why do we need to remove SSIM and Smoothness loss? Isn"t structural similarity and smoothing of the depth quite important?

@jonbarron
Copy link
Owner

jonbarron commented Mar 10, 2020 via email

@rvarun7777
Copy link
Author

I will try it out. Will share my findings here. I think you missed this one!

If you call the loss in general.py, it should never go negative. The loss produced by adaptive.py is actually a negative log-likelihood, so it can go negative depending on the value of the scale parameter. Could you kindly elaborate on this? Doesn't the -log(y) yield positive values.
Example: NLL: -ln(0.5) = 0.69
How does it drive negative or do we consider the abs(l1) finally?

@jonbarron
Copy link
Owner

jonbarron commented Mar 10, 2020 via email

@rvarun7777
Copy link
Author

be sure to delete the secondary branches of the code that evaluate this loss
at multiple scales, you should only need to evaluate it at the finest scale.

In monodepth2 all the lower scales are upsampled to the highest scale and photometric error is applied on them.

Instead of computing the photometric error on the ambiguous low-resolution images, we first upsample the lower resolution depth maps (from the intermediate layers)
to the input image resolution, and then reproject, resample, and compute the error pe at this higher input resolution. This procedure is similar to matching patches, as low-resolution disparity values will be responsible for warping an entire ‘patch’ of pixels in the high resolution image. This effectively constrains the depth maps at each scale to work toward the same objective i.e. reconstructing the high resolution input target image as accurately as possible.

@jonbarron
Copy link
Owner

jonbarron commented Mar 10, 2020 via email

@yellowYuga
Copy link

There's no reason for NLLs to be non-negative. If a likelihood is > 1, the corresponding NLL will be < 0. Basic distributions like Gaussians do this, if you set sigma to a small value. This will only happen in this code when the scale parameter is small, but it should not be any cause for concern.

On Tue, Mar 10, 2020 at 12:41 PM Varun Ravikumar @.***> wrote: I will try it out. Will share my findings here. I think you missed this one! If you call the loss in general.py, it should never go negative. The loss produced by adaptive.py is actually a negative log-likelihood, so it can go negative depending on the value of the scale parameter. Could you kindly elaborate on this? Doesn't the -log(y) yield positive values. Example: NLL: -ln(0.5) = 0.69 How does it drive negative or do we consider the abs(l1) finally? — You are receiving this because you commented. Reply to this email directly, view it on GitHub <#16?email_source=notifications&email_token=AAGZFNXTLI6OAUS7CO4YXNLRG2JUXA5CNFSM4LEF3YD2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEOM3QHI#issuecomment-597276701>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAGZFNT4ESZVZLQWKPRCDSLRG2JUXANCNFSM4LEF3YDQ .

So there is no need to take abs(AdaptiveImageLoss) when loss goes negative?
I use this for HITNet.(https://github.com/google-research/google-research/tree/master/hitnet)
And set:
self.robust = AdaptiveImageLossFunction((960, 320, 1), float_dtype=torch.float32, device=0).

@rvarun7777
Copy link
Author

rvarun7777 commented Jan 12, 2021

@yellowYuga Do not know if this snippet helps you or not. I used it for depth estimation. For more information you can look it up here: SynDistNet

from robust_loss_pytorch import AdaptiveImageLossFunction
self.adaptive_image_loss = AdaptiveImageLossFunction((3, args.input_width, args.input_height),
                                                     torch.float32, args.device, color_space='YUV',
                                                     scale_lo=0.01, scale_init=0.01)
l1_loss = (0.01 * self.adaptive_image_loss.lossfun(torch.abs(target - predicted))).mean(1, True)

@yellowYuga
Copy link

@yellowYuga Do not know if this snippet helps you or not. I used it for depth estimation. For more information you can look it up here: SynDistNet

from robust_loss_pytorch import AdaptiveImageLossFunction
self.adaptive_image_loss = AdaptiveImageLossFunction((3, args.input_width, args.input_height),
                                                     torch.float32, args.device, color_space='YUV',
                                                     scale_lo=0.01, scale_init=0.01)
l1_loss = (0.01 * self.adaptive_image_loss.lossfun(torch.abs(target - predicted))).mean(1, True)

In my experiment,the residual between predicted and target doesn't take abs.That means:
loss = self.robust_loss.lossfun(target - predicted).mean()
Is that correct?
(BTW,when I tested it in fitting curve y=x^2,lossfun(target-pred) is better than lossfun(abs(target-pred)))

@jonbarron
Copy link
Owner

Do not minimize abs(AdaptiveImageLoss), it's totally normal for the loss to go below zero, and adding an abs() will completely break it. Adding an abs() to the input residual passed to the loss will have no effect, so you can do it if you want, but I don't see why you would (the residual is immediately squared in the loss function.

@jonbarron
Copy link
Owner

jonbarron commented Jan 12, 2021

self.robust_loss.lossfun(target - predicted).mean() looks right to me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants