Python Numpy 加性白噪声函数

3

接着这个线程,我需要一个可以在我的输入信号上执行加性白高斯噪声(AWGN)的函数。

以下是我的问题:

  • 无法扩展到多个通道
  • 无法扩展到多个批次
  • scale 不在单独的信号水平上

重要条件:

  • 接受任何维度的 numpy 数组,只要最后一维是time
  • numpy.random.normal 中,scale 或标准差(SD)不是全局的,而是依赖于每个信号的 SD。除非我的 AWGN 的预期实现有误,否则该 SD 应设置为整个数据集的 SD 或硬编码?

目前我已经完成了以下工作:

import numpy as np
import matplotlib.pyplot as plt

def add_noise(data): # assume data shape is (batch,channel,time), but it can also support (batch,time), (batch,anything,whatever,channel,time)

    time_axis = len(data.shape)-1
    target_snr_db = 20
    
    data_watts = data ** 2
    sig_avg_watts = np.mean(data_watts, axis=time_axis)
    sig_avg_db = 10 * np.log10(sig_avg_watts)
    noise_avg_db = sig_avg_db - target_snr_db
    noise_avg_watts = 10 ** (noise_avg_db / 10)
    mean_noise = 0
    noise_volts = np.random.normal(mean_noise, np.sqrt(noise_avg_watts), data.shape) # <-- problem here
    # add noise to the original signal
    noise_data = data + noise_volts
    return noise_data

好的,假设我们正在传递一个只有1个通道的信号 (1,1,1000):

x = np.random.rand(1,1,1000)
plt.plot(x[0,0])
plt.show()

y = add_awgn_noise(x)
plt.plot(y[0,0])
plt.show()

这是不正确的,想象一下传递一个具有 10 个信道的信号 (1,10,1000)

x = np.random.rand(1,10,1000)
y = add_awgn_noise(x)

这是不可行的,想象一下同时传递10个信号,每个信号有10个通道(10,10,1000)

x = np.random.rand(1,10,1000)
y = add_awgn_noise(x)
1个回答

1
为了让np.random.normal调用中不同形状的数组可以一起广播,您需要手动告诉numpy您想要沿着哪个轴广播noise_avg_watts
noise_volts = np.random.normal(mean_noise, np.sqrt(noise_avg_watts)[..., np.newaxis], data.shape)

请注意[..., np.newaxis]
如果我理解正确,noise_avg_watts是一个形状为(s[0], s[1], ..., s[n-1])的数组,其中数据的形状为(s[0], s[1], ..., s[n-1], s[n]);也就是说,每个时间序列都有一个标量数值(最后一个轴是时间序列轴)。因此,为了使其与data的形状兼容,我们希望在时间序列轴上“广播”平均值,这就是我们使用[..., np.newaxis]的原因。
这使得numpy将该数组视为与数据相同的形状,其中前(n-1)个轴的每个(n-1)元组的索引对应于整个时间序列中的同一组标准差(因为它是该轴的平均值)。换句话说,对于每个(信号,通道)对,噪声在整个信号的时间序列中具有相同的标准差。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接