能否在np.fft中传入自定义频率轴?及相关FFT技术问询
问题描述
给定M点网格上的函数f,需计算N点网格上的类傅里叶变换值(满足M < N),核心表达式为:
F[n] = np.sum( np.exp(-2j * np.pi * k * n / N) * f[k])
其中k = np.arange(M),n = np.arange(N)。当前通过构造N×M矩阵与f相乘的实现方式,在矩阵规模较大时内存与计算开销极高,希望借助Numpy/Scipy的FFT工具优化,同时需了解如何用FFT计算单个频率点的变换值。
解决方案
一、转化为FFT可处理的形式
你的需求本质是非均匀离散傅里叶变换(NUDFT),可通过两种方式用标准FFT工具实现:
方法1:补零FFT+频率插值(近似解)
当N远大于M时,可通过补零将f扩展到N长度,再利用标准FFT结合插值得到目标结果:
import numpy as np # 1. 将f补零至N长度 f_pad = np.zeros(N, dtype=np.complex128) f_pad[:M] = f # 2. 计算标准FFT F_fft = np.fft.fft(f_pad) # 3. 构造频率轴并插值 fft_freqs = np.fft.fftfreq(N) # 标准FFT的频率点 target_freqs = np.arange(N) / N # 目标频率点 F = np.interp(target_freqs, fft_freqs, F_fft)
注:该方法为近似解,
N与M差距越大,精度越高。
方法2:Scipy非均匀DFT工具(精确解)
Scipy提供了直接计算NUDFT的工具,无需构造大矩阵,效率远高于矩阵乘法:
import numpy as np from scipy.signal import nudft # 构造目标频率点 omega = np.arange(N) / N # 计算精确非均匀离散傅里叶变换 F = nudft(f, omega, M)
二、计算单个频率点的变换值
若仅需计算某一特定n对应的F[n],直接求和是最高效的方式,无需调用完整FFT:
def single_freq_transform(f, target_n, N, M): k = np.arange(M) exp_term = np.exp(-2j * np.pi * k * target_n / N) return np.sum(f * exp_term)
若非要基于FFT框架实现,反而会增加复杂度,不推荐。
三、无FFT时的内存优化
如果无法使用FFT工具,可通过Numpy广播机制替代矩阵乘法,将内存开销从O(N*M)降至O(M):
k = np.arange(M) n = np.arange(N) # 用广播逐行计算,避免生成完整N×M矩阵 exp_term = np.exp(-2j * np.pi * n[:, None] * k / N) F = np.sum(exp_term * f, axis=1)
内容的提问来源于stack exchange,提问作者Md Elious Ali Mondal
相关产品推荐
相关产品推荐

