Nice programing

파이썬에서 신호에 잡음 추가

nicepro 2020. 10. 28. 21:01
반응형

파이썬에서 신호에 잡음 추가


파이썬에서 시뮬레이션하는 100 개의 빈 신호에 임의의 노이즈를 추가하여보다 현실적으로 만들고 싶습니다.

기본 수준에서 첫 번째 생각은 bin 단위로 이동하여 특정 범위 사이의 임의의 숫자를 생성하고 신호에서 이것을 더하거나 빼는 것입니다.

나는 (파이썬이기 때문에) numpy 또는 무언가를 통해 이것을 수행하는 더 지능적인 방법이 있기를 바랬습니다. (이상적으로는 가우스 분포에서 추출하여 각 빈에 추가하는 숫자도 더 좋을 것이라고 생각합니다.)

회신에 미리 감사드립니다.


저는 코드를 계획하는 단계에 있기 때문에 보여줄 것이 없습니다. 나는 소음을 생성하는 더 정교한 방법이있을 것이라고 생각하고있었습니다.

출력 측면에서 다음 값을 가진 10 개의 빈이있는 경우 :

빈 1 : 1 빈 2 : 4 빈 3 : 9 빈 4:16 빈 5:25 빈 6:25 빈 7:16 빈 8 : 9 빈 9 : 4 빈 10 : 1

다음과 같은 노이즈를 추가 할 수있는 미리 정의 된 함수가 있는지 궁금합니다.

Bin 1 : 1.13 Bin 2 : 4.21 Bin 3 : 8.79 Bin 4 : 16.08 Bin 5 : 24.97 Bin 6 : 25.14 Bin 7 : 16.22 Bin 8 : 8.90 Bin 9 : 4.02 Bin 10 : 0.91

그렇지 않은 경우 빈 단위로 이동하여 가우스 분포에서 선택한 숫자를 각 분포에 추가합니다.

감사합니다.


실제로 시뮬레이션하고있는 전파 망원경의 신호입니다. 결국 시뮬레이션의 신호 대 잡음비를 선택할 수 있기를 원합니다.


노이즈 배열을 생성하여 신호에 추가 할 수 있습니다.

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

... 그리고 저와 같은 사람들은 멍청한 학습 곡선에서 아주 초기에

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

SNR 과 numpy에 의해 생성 된 일반 랜덤 변수를 연결하려는 사람들을 위해 :

[1] SNR 비율, 여기서 P는 평균 전력 이라는 점을 명심해야합니다 .

또는 dB :
[2]SNR dB2

이 경우 이미 신호가 있고 원하는 SNR을 제공하기 위해 잡음을 생성하려고합니다.

소음이 다른 올 수 있지만 은 모델링 작업에 따라, (특히이 라디오 망원경 예를 들어) 좋은 시작이다 소음 첨가제 화이트 가우스 (AWGN) . 이전 답변에서 언급했듯이 AWGN을 모델링하려면 원래 신호에 제로 평균 가우스 확률 변수를 추가해야합니다. 해당 랜덤 변수의 분산은 평균 잡음 전력에 영향을 미칩니다 .

가우스 랜덤 변수 X의 Ep경우 2 차 모멘트 라고도 하는 평균 전력
[3]입니다.전의

따라서 백색 잡음의 전의경우 평균 전력은 분산과 같습니다 전의.

파이썬에서 이것을 모델링 할 때 다음 중 하나를 수행 할 수 있습니다
. 1. 원하는 SNR과 기존 측정 세트를 기반으로 분산을 계산 합니다 . 이는 측정이 상당히 일관된 진폭 값을 가질 것으로 예상하는 경우 작동합니다.
2. 또는 수신기 잡음과 같은 것과 일치하도록 잡음 전력을 알려진 수준으로 설정할 수 있습니다. 수신기 소음은 망원경을 여유 공간으로 향하고 평균 전력을 계산하여 측정 할 수 있습니다.

어느 쪽이든 신호에 노이즈를 추가하고 dB 단위가 아닌 선형 공간에서 평균을 취하는 것이 중요합니다.

다음은 신호를 생성하고 전압, 전력 (와트), 전력 (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()

생성 된 신호

다음은 원하는 SNR을 기반으로 AWGN을 추가하는 예입니다.

# 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()

타겟 SNR로 신호

다음은 알려진 잡음 전력을 기반으로 AWGN을 추가하는 예입니다.

# 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()

목표 소음 수준이있는 신호


pandas 데이터 프레임 또는 numpy ndarray 내에로드 된 다차원 데이터 세트에 노이즈를 추가하려는 사람들을 위해 다음과 같은 예가 있습니다.

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
""" 

위의 멋진 답변. 최근에 시뮬레이션 된 데이터를 생성해야했는데 이것이 제가 사용하게 된 것입니다. 다른 사람에게도 도움이되는 경우 공유,

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

참고 URL : https://stackoverflow.com/questions/14058340/adding-noise-to-a-signal-in-python

반응형