如何通过Python:NumPy/SciPy在频域直接生成高斯分布的随机样本?

How to generate random samples of Gaussian distribution directly in the frequency domain through Python: NumPy/SciPy?

可以使用 NumPy 轻松地从正态(高斯)分布中抽取(伪)随机样本:

import numpy as np
mu, sigma = 0, 0.1 # mean and standard deviation
s = np.random.normal(mu, sigma, 1000)

现在,考虑s的快速傅里叶变换:

from scipy.fftpack import fft
sHat = fft(s)

考虑到,据推测,直接在频域中生成高斯随机数对于各种应用可能更聪明(?)(因此,高效?),并且"the Fourier transform of white noise is white noise", and reportedly sHat can be generated directly without the Fourier-transform of s as theoretically shown herein;

请问新手(比如我)如何实现这样一个有用的想法?有利的是,对我在网络上找不到的可用实现的引用?


以下是我对上述理论解释的代码尝试:

import numpy as np 
from scipy.fftpack import ifft

N = 100
gaussComplex = np.full(shape=N, dtype=complex, fill_value=0.+0.j)

mu, sigma = 0, 1
s = np.random.normal(mu, sigma, N)

iters = np.arange(N) # 0..N-1

# 0..N/2-1
for i, item in enumerate(iters[:N/2]):
    gaussComplex[i] = complex(s[i], s[i+N/2])

conjugateGaussComplex = np.conjugate(gaussComplex)

# N/2..N-1
for i, item in enumerate(iters[N/2:]):
    gaussComplex[item] = conjugateGaussComplex[N-item]

sNew = ifft(gaussComplex)

ssNew 的比较揭示了以下内容,因为我预计它们是相同的:

plt.plot(sHat.real, 'blue')
plt.plot(s, 'red')

the Fourier transform of white noise is white noise

这是事实,但这并不意味着它们完全相同 - 否则进行 FFT 就没有多大意义。

如果绘制 sfft(s) 的实部,您会发现转换后的噪声具有更高的值。

相反,如果用标准差为 1 的随机值填充 gaussComplex,则经过逆变换的噪声将具有更低的标准差。这就是你观察到的。

要在频域中生成高斯白噪声的 FFT,您需要对其进行正确缩放。在您的情况下,这应该可以解决问题:

gaussComplex *= np.sqrt(N/2)

您需要按 sqrt(N) 缩放,因为这是 FFT 的归一化因子。此外,您还需要按 1/sqrt(2) 缩放,因为您在 FFT 的实部和虚部中放置了标准偏差为 1 的噪声。 (但是,绝对值应该有标准偏差 1,因此需要除以 sqrt(1+1)。)

使用正确的缩放比例绘制 ssNew 会产生类似这样的结果:

结果并不完全相同(如预期),但噪音在同一范围内变化 - 两者的标准差均为 ~1。