thêm tiếng ồn vào tín hiệu trong python


95

Tôi muốn thêm một số nhiễu ngẫu nhiên vào tín hiệu 100 bin nào đó mà tôi đang mô phỏng bằng Python - để làm cho nó thực tế hơn.

Ở cấp độ cơ bản, suy nghĩ đầu tiên của tôi là đi từng thùng và chỉ tạo một số ngẫu nhiên giữa một phạm vi nhất định và cộng hoặc trừ số này khỏi tín hiệu.

Tôi đã hy vọng (vì đây là python) rằng có thể có một cách thông minh hơn để làm điều này thông qua numpy hoặc một cái gì đó. (Tôi cho rằng lý tưởng nhất là một số được rút ra từ phân phối gaussian và được thêm vào mỗi thùng cũng sẽ tốt hơn.)

Cảm ơn bạn trước bất kỳ câu trả lời nào.


Tôi chỉ đang ở giai đoạn lập kế hoạch mã của mình, vì vậy tôi không có bất cứ điều gì để hiển thị. Tôi chỉ nghĩ rằng có thể có một cách phức tạp hơn để tạo ra tiếng ồn.

Về đầu ra, nếu tôi có 10 thùng với các giá trị sau:

Thùng 1: 1 Thùng 2: 4 Thùng 3: 9 Thùng 4: 16 Thùng 5: 25 Thùng 6: 25 Thùng 7: 16 Thùng 8: 9 Thùng 9: 4 Thùng 10: 1

Tôi chỉ tự hỏi liệu có một chức năng được xác định trước có thể thêm tiếng ồn để cung cấp cho tôi một cái gì đó như:

Thùng 1: 1,13 Thùng 2: 4,21 Thùng 3: 8,79 Thùng 4: 16,08 Thùng 5: 24,97 Thùng 6: 25,14 Thùng 7: 16,22 Thùng 8: 8,90 Thùng 9: 4,02 Thùng 10: 0,91

Nếu không, tôi sẽ chỉ đi từng bin và thêm một số được chọn từ phân phối gaussian cho từng số.

Cảm ơn bạn.


Đó thực sự là một tín hiệu từ kính viễn vọng vô tuyến mà tôi đang mô phỏng. Tôi muốn cuối cùng có thể chọn tỷ lệ tín hiệu trên nhiễu cho mô phỏng của mình.


2
Vui lòng chứng minh mã bạn đã thử hoặc một vấn đề cụ thể mà bạn đang gặp phải. Đầu vào mẫu và đầu ra mong muốn cũng sẽ đi một chặng đường dài.
gddc 27/12/12

2
Đó là loại tín hiệu gì? Bạn muốn giới thiệu loại tiếng ồn nào? "Thực tế" phụ thuộc vào loại tín hiệu. Ví dụ như nhiễu âm thanh không giống như nhiễu hình ảnh.
Diego Basch

Câu trả lời:


125

Bạn có thể tạo một mảng nhiễu và thêm nó vào tín hiệu của bạn

import numpy as np

noise = np.random.normal(0,1,100)

# 0 is the mean of the normal distribution you are choosing from
# 1 is the standard deviation of the normal distribution
# 100 is the number of elements you get in array noise

17
Trong một số ngữ cảnh, có thể hợp lý hơn khi nhân tín hiệu của bạn với một mảng nhiễu (tập trung xung quanh 1), thay vì thêm một mảng nhiễu, nhưng tất nhiên điều đó phụ thuộc vào bản chất của nhiễu mà bạn đang cố gắng mô phỏng.
Edward Loper

69

... Và đối với những người - như tôi - rất sớm trong đường cong học tập khó khăn của họ,

import numpy as np
pure = np.linspace(-1, 1, 100)
noise = np.random.normal(0, 1, 100)
signal = pure + noise

57

Đối với những người cố gắng tạo kết nối giữa SNR và một biến ngẫu nhiên bình thường được tạo bởi numpy:

[1] Tỷ lệ SNR, điều quan trọng cần ghi nhớ là P là công suất trung bình .

Hoặc tính bằng dB:
[2]SNR dB2

Trong trường hợp này, chúng tôi đã có một tín hiệu và chúng tôi muốn tạo ra tiếng ồn để cung cấp cho chúng tôi một SNR mong muốn.

Mặc dù tiếng ồn có thể có các hương vị khác nhau tùy thuộc vào những gì bạn đang lập mô hình, nhưng một khởi đầu tốt (đặc biệt đối với ví dụ về kính viễn vọng vô tuyến này) là Tiếng ồn Gaussian Trắng Phụ gia (AWGN) . Như đã nêu trong các câu trả lời trước, để lập mô hình AWGN, bạn cần thêm biến ngẫu nhiên gaussian trung bình bằng 0 vào tín hiệu ban đầu của mình. Phương sai của biến ngẫu nhiên đó sẽ ảnh hưởng đến công suất nhiễu trung bình .

Đối với biến ngẫu nhiên Gaussian X, công suất trung bình Ep, còn được gọi là thời điểm thứ hai , là
[3] Ví dụ

Vì vậy, đối với tiếng ồn trắng, Ví dụvà công suất trung bình sau đó bằng phương sai Ví dụ.

Khi lập mô hình này trong python, bạn có thể
1. Tính toán phương sai dựa trên SNR mong muốn và tập hợp các phép đo hiện có, sẽ hoạt động nếu bạn mong đợi các phép đo của mình có giá trị biên độ khá nhất quán.
2. Ngoài ra, bạn có thể đặt công suất tiếng ồn ở một mức đã biết để phù hợp với một số thứ như tiếng ồn của máy thu. Tiếng ồn máy thu có thể được đo bằng cách hướng kính thiên văn vào không gian trống và tính toán công suất trung bình.

Dù bằng cách nào, điều quan trọng là đảm bảo rằng bạn thêm nhiễu vào tín hiệu của mình và lấy giá trị trung bình trong không gian tuyến tính chứ không phải đơn vị dB.

Dưới đây là một số mã để tạo tín hiệu và biểu đồ điện áp, công suất tính bằng Watts và công suất tính bằng dB:

# Signal Generation
# matplotlib inline

import numpy as np
import matplotlib.pyplot as plt

t = np.linspace(1, 100, 1000)
x_volts = 10*np.sin(t/(2*np.pi))
plt.subplot(3,1,1)
plt.plot(t, x_volts)
plt.title('Signal')
plt.ylabel('Voltage (V)')
plt.xlabel('Time (s)')
plt.show()

x_watts = x_volts ** 2
plt.subplot(3,1,2)
plt.plot(t, x_watts)
plt.title('Signal Power')
plt.ylabel('Power (W)')
plt.xlabel('Time (s)')
plt.show()

x_db = 10 * np.log10(x_watts)
plt.subplot(3,1,3)
plt.plot(t, x_db)
plt.title('Signal Power in dB')
plt.ylabel('Power (dB)')
plt.xlabel('Time (s)')
plt.show()

Tín hiệu được tạo

Dưới đây là một ví dụ để thêm AWGN dựa trên SNR mong muốn:

# Adding noise using target SNR

# Set a target SNR
target_snr_db = 20
# Calculate signal power and convert to dB 
sig_avg_watts = np.mean(x_watts)
sig_avg_db = 10 * np.log10(sig_avg_watts)
# Calculate noise according to [2] then convert to watts
noise_avg_db = sig_avg_db - target_snr_db
noise_avg_watts = 10 ** (noise_avg_db / 10)
# Generate an sample of white noise
mean_noise = 0
noise_volts = np.random.normal(mean_noise, np.sqrt(noise_avg_watts), len(x_watts))
# Noise up the original signal
y_volts = x_volts + noise_volts

# Plot signal with noise
plt.subplot(2,1,1)
plt.plot(t, y_volts)
plt.title('Signal with noise')
plt.ylabel('Voltage (V)')
plt.xlabel('Time (s)')
plt.show()
# Plot in dB
y_watts = y_volts ** 2
y_db = 10 * np.log10(y_watts)
plt.subplot(2,1,2)
plt.plot(t, 10* np.log10(y_volts**2))
plt.title('Signal with noise (dB)')
plt.ylabel('Power (dB)')
plt.xlabel('Time (s)')
plt.show()

Báo hiệu với SNR mục tiêu

Và đây là một ví dụ để thêm AWGN dựa trên công suất nhiễu đã biết:

# Adding noise using a target noise power

# Set a target channel noise power to something very noisy
target_noise_db = 10

# Convert to linear Watt units
target_noise_watts = 10 ** (target_noise_db / 10)

# Generate noise samples
mean_noise = 0
noise_volts = np.random.normal(mean_noise, np.sqrt(target_noise_watts), len(x_watts))

# Noise up the original signal (again) and plot
y_volts = x_volts + noise_volts

# Plot signal with noise
plt.subplot(2,1,1)
plt.plot(t, y_volts)
plt.title('Signal with noise')
plt.ylabel('Voltage (V)')
plt.xlabel('Time (s)')
plt.show()
# Plot in dB
y_watts = y_volts ** 2
y_db = 10 * np.log10(y_watts)
plt.subplot(2,1,2)
plt.plot(t, 10* np.log10(y_volts**2))
plt.title('Signal with noise')
plt.ylabel('Power (dB)')
plt.xlabel('Time (s)')
plt.show()

Tín hiệu với mức ồn mục tiêu


8

Đối với những người muốn thêm nhiễu vào tập dữ liệu đa chiều được tải trong khung dữ liệu gấu trúc hoặc thậm chí là một ndarray numpy, đây là một ví dụ:

import pandas as pd
# create a sample dataset with dimension (2,2)
# in your case you need to replace this with 
# clean_signal = pd.read_csv("your_data.csv")   
clean_signal = pd.DataFrame([[1,2],[3,4]], columns=list('AB'), dtype=float) 
print(clean_signal)
"""
print output: 
    A    B
0  1.0  2.0
1  3.0  4.0
"""
import numpy as np 
mu, sigma = 0, 0.1 
# creating a noise with the same dimension as the dataset (2,2) 
noise = np.random.normal(mu, sigma, [2,2]) 
print(noise)

"""
print output: 
array([[-0.11114313,  0.25927152],
       [ 0.06701506, -0.09364186]])
"""
signal = clean_signal + noise
print(signal)
"""
print output: 
          A         B
0  0.888857  2.259272
1  3.067015  3.906358
""" 

1

Trong cuộc sống thực, bạn muốn mô phỏng một tín hiệu với tiếng ồn trắng. Bạn nên thêm vào tín hiệu các điểm ngẫu nhiên có phân phối Gaussian Bình thường. Nếu chúng ta nói về một thiết bị có độ nhạy được cho bằng đơn vị / SQRT (Hz) thì bạn cần phải tính độ lệch chuẩn của các điểm của bạn từ nó. Ở đây tôi cung cấp hàm "white_noise" thực hiện điều này cho bạn, phần còn lại của một đoạn mã là trình diễn và kiểm tra xem nó có đúng như những gì nó cần không.

%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal

"""
parameters: 
rhp - spectral noise density unit/SQRT(Hz)
sr  - sample rate
n   - no of points
mu  - mean value, optional

returns:
n points of noise signal with spectral noise density of rho
"""
def white_noise(rho, sr, n, mu=0):
    sigma = rho * np.sqrt(sr/2)
    noise = np.random.normal(mu, sigma, n)
    return noise

rho = 1 
sr = 1000
n = 1000
period = n/sr
time = np.linspace(0, period, n)
signal_pure = 100*np.sin(2*np.pi*13*time)
noise = white_noise(rho, sr, n)
signal_with_noise = signal_pure + noise

f, psd = signal.periodogram(signal_with_noise, sr)

print("Mean spectral noise density = ",np.sqrt(np.mean(psd[50:])), "arb.u/SQRT(Hz)")

plt.plot(time, signal_with_noise)
plt.plot(time, signal_pure)
plt.xlabel("time (s)")
plt.ylabel("signal (arb.u.)")
plt.show()

plt.semilogy(f[1:], np.sqrt(psd[1:]))
plt.xlabel("frequency (Hz)")
plt.ylabel("psd (arb.u./SQRT(Hz))")
#plt.axvline(13, ls="dashed", color="g")
plt.axhline(rho, ls="dashed", color="r")
plt.show()

Tín hiệu có nhiễu

PSD


0

Câu trả lời tuyệt vời ở trên. Gần đây tôi có nhu cầu tạo dữ liệu mô phỏng và đây là những gì tôi đã sử dụng. Chia sẻ trong trường hợp cũng hữu ích cho những người khác,

import logging
__name__ = "DataSimulator"
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

import numpy as np
import pandas as pd

def generate_simulated_data(add_anomalies:bool=True, random_state:int=42):
    rnd_state = np.random.RandomState(random_state)
    time = np.linspace(0, 200, num=2000)
    pure = 20*np.sin(time/(2*np.pi))

    # concatenate on the second axis; this will allow us to mix different data 
    # distribution
    data = np.c_[pure]
    mu = np.mean(data)
    sd = np.std(data)
    logger.info(f"Data shape : {data.shape}. mu: {mu} with sd: {sd}")
    data_df = pd.DataFrame(data, columns=['Value'])
    data_df['Index'] = data_df.index.values

    # Adding gaussian jitter
    jitter = 0.3*rnd_state.normal(mu, sd, size=data_df.shape[0])
    data_df['with_jitter'] = data_df['Value'] + jitter

    index_further_away = None
    if add_anomalies:
        # As per the 68-95-99.7 rule(also known as the empirical rule) mu+-2*sd 
        # covers 95.4% of the dataset.
        # Since, anomalies are considered to be rare and typically within the 
        # 5-10% of the data; this filtering
        # technique might work 
        #for us(https://en.wikipedia.org/wiki/68%E2%80%9395%E2%80%9399.7_rule)
        indexes_furhter_away = np.where(np.abs(data_df['with_jitter']) > (mu + 
         2*sd))[0]
        logger.info(f"Number of points further away : 
        {len(indexes_furhter_away)}. Indexes: {indexes_furhter_away}")
        # Generate a point uniformly and embed it into the dataset
        random = rnd_state.uniform(0, 5, 1)
        data_df.loc[indexes_furhter_away, 'with_jitter'] +=  
        random*data_df.loc[indexes_furhter_away, 'with_jitter']
    return data_df, indexes_furhter_away

0

AWGN Tương tự với Hàm Matlab

def awgn(sinal):
    regsnr=54
    sigpower=sum([math.pow(abs(sinal[i]),2) for i in range(len(sinal))])
    sigpower=sigpower/len(sinal)
    noisepower=sigpower/(math.pow(10,regsnr/10))
    noise=math.sqrt(noisepower)*(np.random.uniform(-1,1,size=len(sinal)))
    return noise
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.