快速傅里叶变换 FFT
傅里叶级数回忆
是平方可积空间 的一组函数的基,对于空间中的任意函数,我们都有
拟合公式
从上述这个公式我们可以看出,傅里叶级数是将函数投影到不同频率的 和 的空间上的,或者在信号领域,我们可以将这个 写作 表示基频的整数倍频率空间
分解的过程中,对于每一个 ,我们都得到了对应的幅值,这就组成了一个函数关系(自变量为 ,因变量为幅值,即相应频率信号的强度)我们称之为频谱函数。
傅里叶变换回忆
这个公式表示将一个时域空间的函数通过傅里叶变换变成了 频域函数,表示在某一个频率处的强度
傅里叶变换和傅里叶级数的联系
傅里叶级数是傅里叶变换的离散形式,而傅里叶变换是傅里叶级数在周期趋于无穷大时的极限情况
离散傅里叶变换 DFT
傅里叶变换的目的就是得到信号的频谱密度函数(自变量是 𝜔 ,因变量是信号幅值在频域中的分布密度,即单位频率信号的强度),它实际上揭示了信号的强度和频率的关系
采样
首先我们说明狄拉克单位冲激函数对于采样的描述:
$$\int_{-\infty}^{\infty}\delta(t-t_0)f(t)dt=f(t_0)$$
那么我们在时域上将每一个通过狄拉克函数进行筛选
的点叠加起来就可以得到时域上的采样函数了,我们称之为 梳状函数,表达式
\delta_s(t)=\sum_{n=-\infty}^\infty \delta(t-nT_s)$$ 那么我们用时域上的连续信号与之相乘(其实是离散形式的卷积)就得到了 $$f_s=\sum_{n=-\infty}^\infty f(t)\delta(t−nT_s)
时域离散化计算
对于采样得到的 进行傅里叶变换。
根据傅里叶变换的定义:
则 𝑋_𝑠(𝜔)=∫_{−∞}^∞(∑_{𝑛=−∞}^∞ 𝑥(𝑡)𝛿(𝑡−𝑛𝑇_𝑠))𝑒^{−𝑗𝜔𝑡}𝑑𝑡, 交换积分与求和顺序(这里用到了 Fubini 定理或者绝对收敛级数可交换性),得到 𝑋_𝑠(𝜔)=∑_{𝑛=−∞}^∞∫_{−∞}^∞𝑥(𝑡)𝛿(𝑡−𝑛𝑇_𝑠)𝑒^{−𝑗𝑤𝑡}𝑑𝑡, 根据Dirac函数的筛选特性,
𝑋_𝑠(𝜔)=\sum_{𝑛=−∞}^∞𝑥(𝑛𝑇_𝑠)𝑒^{−𝑗𝑤𝑛𝑇_𝑠}
但是不幸的是,这个函数对于 还是一个连续函数
频域离散化计算
对于连续信号 进行 次(N为有限值)采样,采样周期为 。然后对采样得到的信号进行时域上的周期延拓(延拓至正负无穷),这样我们就得到了一个周期为 的函数。对于周期函数而言,它的频谱密度函数是离散化的,这样我们就成功把频域也进行了离散化。
在一个周期内,离散信号的表达式为 𝑥_𝑠(𝑡)=∑_{𝑛=0}^{𝑁−1}𝑥(𝑡)𝛿(𝑡−𝑛𝑇_𝑠)
离散信号的傅里叶变换 𝑋(𝑘𝜔_0)=\frac{1}{𝑇_0}∫_0^𝑇(∑_{𝑛=0}^{𝑁−1}𝑥(𝑡)𝛿(𝑡−𝑛𝑇_𝑠))𝑒^{−𝑗𝑘𝑤_0𝑡}𝑑𝑡
其中, 𝜔_0=2𝜋 / 𝑇_0
交换积分和求和次序, 𝑋(𝑘𝜔_0)=\frac{1}{𝑇_0}∑_{𝑛=0}^{𝑁−1}∫_0^𝑇𝑥(𝑡)𝛿(𝑡−𝑛𝑇_𝑠)𝑒^{−𝑗𝑘𝜔_0𝑡}𝑑𝑡
根据狄拉克函数的筛选特性
𝑋(𝑘𝜔_0)=\frac{1}{𝑁𝑇_𝑠}∑_{𝑛=0}^{𝑁−1}𝑥(𝑛𝑇_𝑠)𝑒^{−𝑗\frac{2𝜋}{𝑁}𝑘𝑛}
为更加简明,令 𝑋[𝑘]=𝑋(𝑘𝜔_0)𝑇_𝑠 , 𝑥[𝑛]=𝑥(𝑛𝑇_𝑠) ,则
𝑋[𝑘]=\frac{1}{𝑁}∑_{𝑛=0}^{𝑁−1}𝑥[𝑛]𝑒^{−𝑗\frac{2𝜋}{𝑁}𝑘𝑛}
复杂度分析
首先对于变量 ,我们需要计算 次的 和 , k 的取值也是
所以整体的复杂度是
至少次数是有限次
快速傅里叶变换 FFT
数理原理
首先我们要解释一下上面 的数理意义, 相当于是时域的 , 相当于是 频率 的 , 相当于是 频谱函数在 处的幅值大小
那么接下来我们分析一下 的等价性,如果可以化简这部分的算法,那么就能降低运算量。
不难发现,当 是偶数的时候,
𝑒^{−𝑗\frac{2𝜋}{𝑁}2𝑛𝑘}=𝑒^{−𝑗\frac{2𝜋𝑛}{𝑁/2}𝑘}=𝑒^{−𝑗\frac{2𝜋𝑛}{𝑁/2}(𝑘+𝑁/2)}
也就是说周期是 .
因此,我们可以将 n 分为奇偶数两类分别求和,其中对奇数部分提取一个 的系数,则剩余部分就是偶数部分,同时定义函数 𝑊[𝑛,𝑘]=𝑒^{−𝑗\frac{2𝜋}{𝑁}𝑛𝑘} , 那么我们有
X[k] = ∑_{𝑛=0}^{𝑁/2−1}𝑥[2𝑛]𝑊[2𝑛,𝑘]+𝑒^{−𝑗\frac{2𝜋}{𝑁}𝑘}∑_{𝑛=0}^{𝑁/2−1}𝑥[2𝑛+1]𝑊[2𝑛,𝑘]
我们令偶数部分为 ,奇数部分提取公因数后的结果为 ,则
, 其中 都是已知且固定的,且 满足
那么, ,
(推导如下)
𝑒^{−𝑗\frac{2𝜋}{𝑁}(𝑘+𝑁/2)}=𝑐𝑜𝑠(−\frac{2𝜋}{𝑁}(𝑘+𝑁/2))+𝑗\ 𝑠𝑖𝑛(−\frac{2𝜋}{𝑁}(𝑘+𝑁/2)) =𝑐𝑜𝑠(−\frac{2𝜋}{𝑁}𝑘−𝜋)+𝑗\ 𝑠𝑖𝑛(−\frac{2𝜋}𝑁𝑘−𝜋) =−𝑒^{−𝑗\frac{2𝜋}𝑁𝑘}
我们可以得出结论
注意这里
蝴蝶结构
其实在上面我们就可以看出,我们会将一个周期为 N 的数据组进行平均分(或者说这就是分治算法的精髓)
然后我们两边齐头并进,如下图

我们有 ,
这个形式我们称之为 蝴蝶结构
逆快速傅里叶变换 IFFT
Evaluation
我们首先从多项式入手,我们对于一个已知系数的多项式,我们可以得到 其位于某些点的值。但是,如果我们已知 点的值,我们如何快速推算 的值?
从奇偶性的角度思考,我们可以将多项式分成 奇数次项 和 偶数次项。再回想上面做的内容,,
总的多项式的等式
我们由此推算
这个操作最牛的地方在于它将一个高次函数降次到 一半的次数,那对于一个人或者电脑来说,次数越低肯定是越好算的。
如果我们想要重复执行一次这个操作,或者说,我们想要递归的执行这个操作直到 base case, 那么我们就需要将 进行配对(就是有正有负,奇偶性的使用很依赖于这个条件),意思就是,我们要构造 都在多项式的 x 坐标上。那么,我们就需要使用 复数的思路。
假设一个复平面中我们有一个单位圆,如果我们要将一个圆 等分, 那么每个节点上面的数就满足 配对要求
所以我们定义变量
然后就有求值等式
使用 python 表示算法思路,就是
1 | def FFT(P): |
Interpolation
首先,大量平行的 evaluation 过程是 可以通过矩阵表示的


眼尖的你一定发现了,这就是范德蒙的矩阵,所以求解这类问题的算法可以查阅范德蒙的矩阵的性质
但是,我们也知道,插值法就是求值法的逆运算,也就是

你还会发现,两个矩阵只有 以及倒数的关系,也就是说,我们可以通过已有点的值进行反向估计差值的系数集合
