python 一维傅里叶 曲线 python快速傅里叶变换求幅值_方程组


在这篇文章中,我们来学习快速傅里叶变换

算法。

对于一个长度为

的离散信号来讲,我们对其取离散傅里叶变换有:

其中

离散傅里叶变换,其逆变换为:

其中

离散逆傅里叶变换。

从式

中我们可以发现,如果要求第

点的

值,我们需要做:

次加法;和:

次乘法运算。这就意味着如果要计算

的值那么总共需要计算

次的乘法和

次的加法。这样的计算量大小在

比较小的时候是体现不出来的,但是当

很大时这样的计算量是十分庞大的。所以,我们要设法改进算法,来减少运算量。

那我们应该从何处入手来解决优化这个算法呢?答案就是从表达式本身入手来解决。因为在式

中我们发现,求和项中含有

这一项,这一项的性质可以说是相当不错的。下面我们就先来研究一下这一项的性质。

我们定义:

将式

代入到式

中我们可以得到:

比如,我们现在有一个长度为

的信号

,则通过式

可以得到:

时,我们可以得到下面的关系式:

将式

写为矩阵形式为:

下面我们就通过研究

来简化式

中的矩阵

性质一— 周期性

此外,由式

还还可以推得:

设:

进而有:

性质二— 对称性

有了这两个性质之后,设

并将方程

分解为两部分:

其中:

为偶数序列;

为奇数序列。

现在,我们使用式

和式

来简化式

中的矩阵

。不过在之前,我们先来看一个特殊情况。

因为:

由式

可知:

所以在式

中有:

这样,通过式

简化后的式

中的矩阵

为:

此外,我们利用式

还可以得到:

因此,在矩阵

中可以利用式

消掉几项:

通过式

可以进一步对矩阵

进行化简:

而对于剩下的两项,我们依然可以使用对称性进一步简化:

最后,经过式

简化之后的矩阵为:

见最终的矩阵

带入到式

中得到:

现在我们调换矢量

的第二行和第第三行,而且为了保持结果不变,我们也同时调换矩阵

的第二列和第三列,之后得到:

现定义:

我们将

进行分块:

我们现在也将矢量

进行分块:

进而将式

和式

代入到式

中有:

显然,矩阵

只与矢量

有关 ,而矩阵

只与矢量

有关 。

现在,我们矩阵方程

写为方程组的形式:

现在定义:

将式

各式代入到式

中可以得到:

由式

我们可以知道,中间变量

都是通过一次加法计算得到,而通过式

又可以知道

各是通过一次加法得到的,这样通过简化之后计算一个长度为

的序列的加法次数为

次,而进行简化之前则需要做

次加法。下面我们再来看看乘法的次数是如何变化的。在式

中,我们总共做了:

次乘法,而在获得中间变量

的时候没有进行乘法运算,所以,乘法总共进行了

次,相比于为简化之前的

次是显著减少的。

在继续之前我们先来明确一个问题就是:

所以:

同理有:

将式

代入到式

中可得:

现在我们来研究一下

的周期性:

利用式

可以将式

表示为:

下面,我们来

信号流图中的基本结构单元—

蝶形单元。我们还是先通过一个具体的例子来了解何为蝶形单元:

python 一维傅里叶 曲线 python快速傅里叶变换求幅值_快速傅里叶变换 python_02

图片一:蝶形单元示例。

图片一所示的蝶型单元所对应的方程组为:

在方程组

中,我们总共进行了两次乘法运算和两次加法运算。现在,我们想设法将图片一中的蝶型单元进行简化,使其仅进行一次乘法运算。

python 一维傅里叶 曲线 python快速傅里叶变换求幅值_快速傅里叶变换 python_03

图片二:经过简化后的图片一中的蝶型单元。

经过简化后的方程组为:

.

这样就相当于

先和

做一次乘法运算,然后再与

进行相加减(两次加法运算)得到

我们再来看另外一个:

python 一维傅里叶 曲线 python快速傅里叶变换求幅值_傅里叶变换_04

图片三:蝶型单元示例2。

图片三所示的蝶形单元所对应的方程组为:

我们做与图片一类似的简化,为了将乘法运算的次数减到一次:

python 一维傅里叶 曲线 python快速傅里叶变换求幅值_傅里叶变换_05

图片四:经过简化后的图片三中的蝶型单元。

我们将图片四和图片二的这两个蝶形单元堆叠起来就会得到:

python 一维傅里叶 曲线 python快速傅里叶变换求幅值_分块_06

图片五:蝶形图堆叠。

通过上面的分析我们知道,在这样一个堆叠起来的蝶形单元中,总共进行了

次乘法运算和

次加法运算,而这是

时的情况。所以,对于一个长度为

的序列来讲,求得中间变量

,我们总共需要计算

次乘法运算和

次加法运算。再由中间变量

求得最后的矢量

也是一个这样堆叠起来的蝶型单元:

python 一维傅里叶 曲线 python快速傅里叶变换求幅值_快速傅里叶变换 python_07

图片六:蝶型单元堆叠。

这里蝶形单元出现交叉的原因是输出的

并未参与换位。显然,这样一个蝶形单元也进行了

次的乘法运算和

次的加法运算。所以,对于一个长度为

的序列来讲,从

总共需要做

次乘法运算和

次的加法运算。所以,一般的对于一个长度为

的序列而言,从

总共需要做

次乘法运算和

次的加法运算。相比较未优化前的

次乘法运算和

次加法运算有显著的减少。

现在,我们将

时的完整的信号流图画出来:

python 一维傅里叶 曲线 python快速傅里叶变换求幅值_python 一维傅里叶 曲线_08

图片七:序列长度为N=4的完整的信号流图。

从图片七中我们可以看出,一个长度为

的序列最开始只进行了一次奇偶分解,而且分为了两组蝶形流程图,分别是从

到中间变量为一组(第

组)和从中间变量到

为一组(第

组)。对于

的情况,这种奇偶分解和蝶形图分解应该被贯彻下去。

一般形式的蝶形单元为(第

组 ):

python 一维傅里叶 曲线 python快速傅里叶变换求幅值_分块_09

图片8:一般形式的蝶型单元。

输入端上节点:

输入端下节点:

输出端上节点:

输出端下节点:

在图片八中所示的一般形式的蝶型单元中,输入下节

先乘以

之后再与输入上节点

进行相加减,得到输出上、下节点

。所以,在这样一个一般形式的蝶型单元中,总共进行了

次加法运算和

次乘法运算。

蝶型单元具有以下特点:

每一个蝶型单元都是独立的;

每一级(组)都有 个蝶形单元,其中 为序列长度;

长度为 的序列具有 级(组)的蝶形,且每级可以分为 小组蝶形单元, 代表级数。

的特殊情况推广得到。为了便于理解,各位可以通过

的特殊情况进行理解。

此外,对于图片八所示的蝶形图,它对应了下面的方程组:

由蝶形单元的独立性可知,由两点构成的蝶型单元运算过后就不会再参与其他蝶型单元的运算了。

对于长度为

的序列来讲,其具有

级的蝶型单元,而每一级又有

个独立的蝶形单元,所以,整个信号流图所需要的乘法运算次数为:

整个信号流图所需要的加法运算次数为:

这便是采用了

算法之后所需要进行的乘法和加法的运算次数。随着采样点的增加,采用

算法比直接计算一个序列的

要快的多。

我们以

的序列为例,

的序列共进行了两次奇偶分组:

进行分组之前的序号为:

第一次分组之后的序号为:

第二次分组之后的序号为:

之后按第二次分组的序号进行运算,最终得到的结果的序号是:

如果我们将未分组之前的序号和第二次分组之后的序号进行二进制编码可以得到:

我们可以看出用红色标记出的二进制编码实际上是进行了码位倒置(实际上没用红色标记的二进制编码也进行了码位倒置,之后倒置前后结果一致)。所以说,对于一个

的序列来讲,分组之前的序号和最后一次(第二次)分组之后的序号在二进制上来讲实际上是发生了码位倒置。

使用

算法的注意事项:

  • 信号离散时,采样频率为 频率;
  • 必须为 的整数次幂;
  • 数据长度必须足够长: 。其中, 为数据分辨率; 为序列长度(序列点数); 为采样周期, 是数据的实际长度。