WheatField
WheatField

“恶劣”的高斯噪音

October 10, 20221620 words, 9 min read
Authors

什么是高斯噪音

高斯噪音(Gaussian Noise, GN)是一种服从高斯分布的随机噪声,是一种非常常见的噪声类型,概率密度函数为 f(x)=12πσe(xμ)22σ2f(x) = \frac{1}{\sqrt{2\pi}\sigma}e^{-\frac{(x-\mu)^2}{2\sigma^2}}μ\mu 是均值,σ\sigma 是标准差。

对于高斯噪音有人给出的评价是:“高斯噪音是自然界中最恶劣的噪音”。当然,这里的恶劣不是指音量大,而是指对信号的干扰程度比较大。从信息论上讲,这个论断的依据是高斯噪音引入了最大的不确定性。再细一点,根据最大熵定理:如果平均功率受限,那么当信源符合高斯分布时,信源的熵最大。而熵刻画了信息的不确定性,熵越大,说明噪声的不确定性越大,对信源的干扰也大。即如果假定功率受限,高斯噪声是最干扰信息的一类噪声。

简单回顾一下最大熵

估算一个未知分布,最大熵模型的目标是找到一个概率分布 p(x)p(x),使得 p(x)p(x) 满足所有已知的约束条件,同时使得 p(x)p(x) 的熵最大。要最大化连续分布的熵

maxpPH(p)=maxpPp(x)logp(x)dx\max_{p \in \mathbb{P}} H(p) = \max_{p \in \mathbb{P}} - \int p(x) \log p(x) dx

约束条件是:

  • 概率密度函数积分为 1:f(x)dx=1\int f(x) dx = 1
  • 给定方差:(xμ)2f(x)dx=σ2\int (x-\mu)^2 f(x) dx = \sigma^2
  • 均值:xf(x)dx=μ\int x f(x) dx = \mu

可以构建拉格朗日函数:

L=f(x)lnf(x)dx+λ1(f(x)dx1)+λ2((xμ)2f(x)dxσ2)+λ3(xf(x)dxμ)L = -\int f(x) \ln f(x) dx + \lambda_1(\int f(x) dx - 1) + \lambda_2(\int (x-\mu)^2 f(x) dx - \sigma^2) + \lambda_3(\int x f(x) dx - \mu)

其中 λ1\lambda_1, λ2\lambda_2, λ3\lambda_3 是拉格朗日乘数。

要求得极值条件,先对 f(x)f(x) 求变分,并令其等于零:

δLδf(x)=lnf(x)1+λ1+λ2(xμ)2+λ3x=0\frac{\delta L}{\delta f(x)} = -\ln f(x) - 1 + \lambda_1 + \lambda_2(x-\mu)^2 + \lambda_3x = 0

解以上方程,我们得到: f(x)=eλ11+λ2(xμ)2+λ3xf(x) = e^{\lambda_1 - 1 + \lambda_2(x-\mu)^2 + \lambda_3x}

简化以上表达式,令 A=eλ11A = e^{\lambda_1 - 1}, B=λ22B = -\frac{\lambda_2}{2}, C=λ32λ2μC = \lambda_3 - 2\lambda_2\mu,我们得到:

f(x)=AeBx2+Cx f(x) = A e^{Bx^2 + Cx}

利用约束条件确定 AA, BB, CC 的值。最终,我们得到:f(x)=1σ2πe(xμ)22σ2f(x) = \frac{1}{\sigma\sqrt{2\pi}} e^{-\frac{(x-\mu)^2}{2\sigma^2}},这正是正态分布的概率密度函数。

当然这里的前提是,我们知道均值和方差。没有其他信息的情况下,我们假定数据服从正态分布是最保守的选择,因为它最大化了我们对数据的不确定性。

这是从统计学的角度来看待高斯噪声。再从概率论上考虑,根据中心极限定理,大量相互独立的随机变量,其均值的分布以正态分布为极限。现实世界中的噪声可能是由很多个来源不同的小的随机噪声累积形成的,即 noise=iri\text{noise} = \sum_i{r_i} ,其中 rir_i 为随机噪声。也就是说一个系统中如果有很多个小的随机噪声,那么这些噪声的和就会趋向于高斯分布,或者说高斯噪音是系统真实噪声的一个很好的近似。

综合以上两方面,也就很容易理解 GN 在机器学习领域中广泛应用的原因。比如深度学习中知名的去噪自编码器(DAE)就是通过引入高斯噪声来训练模型,完成对数据的去噪(重建),从而得到一个更加鲁棒的模型。

Gaussian Noise 的简单实现

一般在应用中使用的都是加性噪声模型,即信号是原始信号和噪声的叠加,即 y=x+ny = x + n,其中 xx 是原始信号,nn 是噪声。一个直观的实现是先生成一个和原始数据维度一样的高斯分布的随机数,然后加到原始数据上。

import numpy as np
dim = 100
noise = np.random.normal(0, 1, dim)
new_data = source_data + noise

上面的实现中还需要解决的一个问题,就是如何确定噪声的范围,即如何设定高斯噪音中的期望与方差?方差越大,噪声越大,但是如果方差过大,可能会导致噪声过大,影响原始数据的特征。所以我们需要一个合适的方法来确定噪声的范围。

一种方法是通过信噪比(Signal to Noise Ratio, SNR)来控制噪声的范围。信噪比,顾名思义,即是信号与噪声的比例,计量单位为 dB,计算方式是

SNR=10log(Ps/Pn)\text{SNR} = 10 \log(Ps/Pn)

其中 Ps,PnPs, Pn分别表示信号和噪声的有效功率。信噪比大于 1,说明信号比噪声大,信噪比小于 1,说明噪声比信号大。信噪比越大,说明信号越清晰,噪声越小。从放大器(比如音箱)的角度考虑,设备的信噪比越高表明它产生的噪声越少。一般来说,信噪比越大,说明混在信号里的噪声越小,声音回放的音质量越高。

因此,在确定 SNR 后,我们可以通过下面的代码来生成噪声,然后把噪声加到原始数据上,即得到引入噪声的数据。

这样的噪声也经常被称为加性高斯白噪声(Additive white Gaussian noise, AWGN),因为噪声是可以叠加的,服从高斯分布,且是白噪声。

# Additive white gassusian noise
import numpy as np

def awgn(source: np.ndarray, seed: int = 0, snr: float = 70.0):
    """ snr = 10 * log10( xpower / npower )
    """
    random.seed(seed)
    snr = 10**(snr / 10.0)
    xpower = np.sum(source**2) / len(source)
    npower = xpower / snr
    noise = np.random.normal(scale=np.sqrt(npower), size=source.shape)
    return source + noise

if __name__ == '__main__':
    t = np.linspace(1, 100, 100)
    source = 10 * np.sin(t / (2 * np.pi))
    # four subplots
    f, axarr = plt.subplots(2, 2)
    f.suptitle('Additive white gassusian noise')
    for i, snr in enumerate([10, 20, 30, 70]):
        with_noise = awgn(source, snr=snr)
        axarr[i // 2, i % 2].plot(t, source, 'b', t, with_noise, 'r')
        axarr[i // 2, i % 2].set_title('snr = {}'.format(snr))
    plt.show()

下图是 SNR 分别为 10dB, 20dB, 30dB, 70dB 的原始数据-带噪声数据对比图像,从图可见,当 SNR=70dB 时,几乎看不出噪声的存在。不过仔细观察,还是能看到有的地方与原始分布有出入,也就是说,即使 SNR 很高,也不能完全消除噪声。 这也是为什么麦克风导购文章中,良心博主一般给的建议是信噪比低于 80dB 的都不要考虑。

参考