繁体   English   中英

为什么我自己的 N 维快速傅立叶变换实现与 NumPy 的结果不同?

[英]Why does my own implementation of Fast Fourier Transform in N dimensions give different results than NumPy's?

我为 N 维快速傅立叶变换编写了以下代码,但它没有给我与 numpy 的 function 相同的结果。

def nffourier(f, direct):
    dim = f.ndim  
    N = f.shape
    G = np.zeros(f.shape, dtype=complex)
    G = f
    
    for k in range(dim):
        for i in range(N[k]):
            aux = G[(slice(None),) * (k) + (i,)]
            trans = ffourier(aux, direct)
            G[(slice(None),) * (k) + (i,)] = trans
            
    return G

我在 1d 中计算 FFT 的代码如下:

def ffourier(f, direct):
    N = len(f)
    
    M = int(m.log(N)/m.log(2))
        
    G = []
    order = []
    
    for i in range(N):
        order.append(int(bin(i)[2:]))
    
    digitos = len(aux)
    for i in range(N):
        contenido_aux = str(int(order[i]))
        aux = len(str(order[i]))
        if(aux<digitos):
            añadir=digitos-aux
            for k in range(añadir):
                contenido_aux = '0'+contenido_aux
        G.append(contenido_aux)
    for i in range(len(G)):
        G[i] = G[i][::-1]
    

    for i in range(len(G)):
        G[i] = int(G[i], 2)
    for i in range(len(G)):
        G[i] = f[G[i]]
    

    
   
    if direct == False:
        signo = 1
    else:
        signo = -1


    kmax = 1
    kmax = int(kmax)
    for alfa in range(1,M+1):
        w1 = np.exp(signo*1j*2*m.pi/(2**alfa))
        kmax = int(2*kmax)
        W = 1
        for k in range(0, int(kmax/2)-1+1):
            for s in range(0, N-1+1, int(kmax)):
                T0 = G[s+k]
                T1 = G[s+k+int(kmax/2)]*W
                G[s+k]=T0+T1
                G[s+k+int(kmax/2)]=T0-T1
            W=W*w1
    cte = 1/m.sqrt(N)
    for i in range(0, N-1+1):
        G[i] = G[i]*cte 
    return G

它的基本原理很难解释,它基于位反转,但我已经检查它是否正常工作,所以问题出在 N 维代码上。

如果k为 2,则索引G[(slice(None),) * (k) + (i,)]与 5D 数组的G[:,:,i,:,:]相同。这是不是您要生成的索引。 您需要提取单个一维子数组,并遍历所有此类子数组。

我认为让它适用于任意 N 维数组的最简单方法是在 N 的循环中置换数组维度,这样你总是在最后一个维度上应用 1D FFT,并展平其余的维度维度以轻松循环遍历它们。 像这样的东西(未测试):

def nffourier(f, direct):
    dim = f.ndim  
    G = f.astype(complex)
    
    for k in range(dim):
        G = np.moveaxis(G, 0, -1)  # shifts the dimensions by one to the left
        shape = G.shape
        m = shape[-1]
        G = np.reshape(G, (-1, m))  # flattens all but last dimension
        m = G.shape[0]
        for i in range(m):          # loop over first dimension
            G[i, :] = ffourier(G[i, :], direct)  # apply over last dimension
        G = np.reshape(G, shape)    # return to original shape
    
    # After applying moveaxis dim times, G should have the same it had at the start
    return G

(另请注意,正如我们已经在评论中讨论的那样, G = f行导致 output 数组Gf的类型相同,可能不复杂,因此也会导致错误。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM