-
Notifications
You must be signed in to change notification settings - Fork 202
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
What about upsampling? #28
Comments
Thanks for the question! Yes, when upsampling, blurring should be applied after. When downsampling, it should be applied before. In both cases, it is applied at the higher resolution. To fully understand why, I recommend taking a signal processing course and seeing what these operations are actually doing in the Fourier domain. |
I see... The more I think about it the more it makes sense. I will follow your recommendation. Thanks for the quick reply. |
May I ask one more question? I read your previous reply related to this,
I want to check if I understand correctly the Pytorch implementation. For downsampling we do: For upsampling we do: Is this correct? |
Yes, that's correct. For upsampling, it's not relevant what happens before the convtranspose layer. Just make sure you blur after upsampling. So I would phrase it as:
|
@richzhang Thank you for clarifying. Please if you don't mind I have two more questions:
I think this is true only for strides of 2 (upsampling factor of 2). This is mostly the case anyway so you probably omitted this, but I just want to confirm this as others might use larger factors/stride. |
Do Yes about the stride |
@richzhang - I was trying to see how I could implement upsampling using Here is a simple reproducible code block that seems to confirm this for me: import torch
import numpy as np
# Setup image of zeros with a 2x2 block of 1 in the center
a = np.zeros((6,6))
a[2:4, 2:4] = 1
a_t = torch.from_numpy(a[None, None, :, :])
# Setup filter
filt_1d = np.array([1.,3.,3.,1.])
filt_2d = filt_1d[None,:] * filt_1d[:,None]
# Conv transpose upsampling
filt = 4*torch.from_numpy(filt_2d[None, None, :, :]/filt_2d.sum())
conv =torch.nn.functional.conv_transpose2d(a_t, filt, stride=2, padding=1)
conv_np = conv.numpy().squeeze()
# Pytorch built-in upsamling
upsample = torch.nn.functional.upsample(a_t, scale_factor=2, mode='bilinear')
# Check that they match
upsample_np = upsample.numpy().squeeze()
np.testing.assert_allclose(upsample_np, conv_np) is None
Am I doing something wrong here? |
Yes, you started with a 2x2 filter |
Thanks for the quick reply! I am treating |
Thanks, got it. I'm not sure if the pytorch implementation is correct. If the signal is properly upsampled, you should be able to do simple subsampling Here's the operation for scipy, which is consistent with import scipy.interpolate
a = np.zeros((5,5))
a[2,2] = 1
sample = np.arange(0,5,.5)
print(scipy.interpolate.interp2d(np.arange(5), np.arange(5), a, kind='linear')(sample, sample)) Output
|
Okay I understand now.
I wouldn't have done that half-index shift. |
Thanks @richardyang . It does appear that Pytorch is doing something weird with its upsampling. Btw, I really enjoyed reading through this paper and the experiments you laid out in it 👍 |
Thank you for your awesome work. I have a question:
What if I want to perform upsampling instead of downsampling? As I understand, aliasing is a problem only when downsampling. But I came across this paper A Style-Based Generator Architecture for Generative Adversarial Networks where they also blur during upsampling, citing your work. Here the blur was applied after upsampling (instead of before as in downsampling). Could you comment on that?
I intend to apply your technique in a VAE or GAN, and I would like to know whether I should include the blur in the decoder/generator.
The text was updated successfully, but these errors were encountered: