How can I create this tensor in PyTorch without using Numpy?

I’d like to be able to create this tensor without using Numpy, but I can’t find the PyTorch equivalent to Numpy’s fft.fftfreq:

import numpy as np	
def get_fft_scale(h, w, decay_power=.75):
    d=.5**.5 # set center frequency scale to 1
    fy = np.fft.fftfreq(h,d=d)[:,None]
    if w % 2 == 1:
        fx = np.fft.fftfreq(w,d=d)[: w // 2 + 2]
    else:
        fx = np.fft.fftfreq(w,d=d)[: w // 2 + 1]        
    freqs = (fx*fx + fy*fy) ** decay_power
    scale = 1.0 / np.maximum(freqs, 1.0 / (max(w, h)*d))
    scale = torch.Tensor(scale).float()[None,None,...,None]
    return scale

Hi,

What is the difference between this and a histogram functions?

So, I guess the question is how to generate the initial tensors then?

>>> import numpy as np
>>> h = 8
>>> d = .5**.5
>>> fy = np.fft.fftfreq(h,d=d)
>>> fy
array([ 0.        ,  0.1767767 ,  0.35355339,  0.53033009, -0.70710678,
       -0.53033009, -0.35355339, -0.1767767 ])

I’m not quite sure. I’m using this tensor for spatial decorrelation of a tensor.

Given this and the definition in their doc, it feels like you can implement it with a simple arange function no?

It looks like I can recreate it with the following function, using torch.arange twice:

def create_freq_tensor(size, cf=.5**.5):
    step=(cf/(size/2))
    end = (step * size)/2
    return torch.cat([torch.arange(0,end=end,step=step), torch.arange(-cf, end=0, step=step)])
1 Like

Nice!
That looks good !

And then I guess this is the full function:

def create_freq_tensor(size, cf=.5**.5, device='cpu'):
    step=(cf/(size/2))
    end = (step * size)/2
    return torch.cat([torch.arange(0, end=end, step=step, device=device), torch.arange(-cf, end=0, step=step, device=device)])

def get_fft_scale(h, w, decay_power=.75, device='cpu'):
    d=.5**.5
    fy = create_freq_tensor(h, device=device)[:,None]
    if w % 2 == 1:
        wadd = 2
    else:
        wadd = 1
    fx = create_freq_tensor(w, device=device)[: w // 2 + wadd]        
    freqs = (fx*fx + fy*fy) ** decay_power
    scale = 1 / torch.max(freqs, torch.full_like(freqs, 1.0 / (max(w, h)*d)))
    return scale[None,None,...,None]

Is there a way I could do it better?

Given that you take only the first half of the output of create_freq_tensor, you might just want a single arange call. and you can remove the cat as well no?

Yes, I can just remove the cat as well and instead do this (based on the NumPy code):

# NumPy fft.fftfreq in PyTorch
def pytorch_fftfreq(n, d=1.0, device='cpu'):		
    results = torch.empty(n, device=device)
    s = (n-1) // 2 + 1
    results[:s] = torch.arange(0, s, device=device)
    results[s:] = torch.arange(-(n//2), 0, device=device)
    return results * (1.0 / (n * d))
1 Like