You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何用FFT乘积对一维数组做卷积时结果值存在差异?

为什么FFT逐元素相乘的逆变换与直接卷积结果存在差异?

你观察到的差异核心原因是循环卷积和线性卷积的区别:

  • scipy.fft.fft 默认对输入序列做长度等于原序列长度的FFT,此时逐元素相乘再逆FFT得到的是循环卷积,结果长度和输入序列一致(这里是4)。
  • np.convolve 默认计算的是线性卷积,结果长度为 len(A) + len(B) - 1(这里是4+4-1=7)。

循环卷积的本质

循环卷积会把线性卷积的结果进行“循环折叠”:将线性卷积中超出输入长度的部分,循环加到前面的对应位置上。以你的例子来说:
线性卷积结果是 [6,23,34,52,50,17,18],循环卷积长度为4,所以每个位置的值是:

  • 第0位:6 + 50 = 56(线性卷积第0位 + 第4位)
  • 第1位:23 + 17 = 40(线性卷积第1位 + 第5位)
  • 第2位:34 + 18 = 52(线性卷积第2位 + 第6位)
  • 第3位:52 + 0 = 52(线性卷积第3位,无对应循环位)
    这正好和你得到的逆FFT结果 [56.+0.j, 40.+0.j, 52.+0.j, 52.-0.j] 完全对应。

如何用FFT得到线性卷积的结果

要让FFT方法等价于线性卷积,需要先对两个序列补零填充,让长度至少为 len(A)+len(B)-1(或者更高效的下一个2的幂长度),此时循环卷积就等同于线性卷积。修正后的代码如下:

import numpy as np
from scipy.fft import fft, ifft

a = [3, 4, 1, 2]
b = [2, 5, 4, 9]
# 计算线性卷积需要的最小长度
min_length = len(a) + len(b) - 1

# 对序列补零到最小长度
a_padded = np.pad(a, (0, min_length - len(a)), mode='constant')
b_padded = np.pad(b, (0, min_length - len(b)), mode='constant')

# 执行FFT、逐元素相乘、逆FFT
fft_a = fft(a_padded)
fft_b = fft(b_padded)
result_fft = ifft(fft_a * fft_b).real.round()  # 取实部并消除浮点误差

print(result_fft)
# 输出:[ 6. 23. 34. 52. 50. 17. 18.]

# 对比线性卷积结果
result_conv = np.convolve(a, b)
print(result_conv)
# 输出:[ 6 23 34 52 50 17 18]

这样两种方法的结果就完全一致了。

内容的提问来源于stack exchange,提问作者Linear Algebra fans

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 02:25:12