Saya ingin menambahkan beberapa gangguan acak ke beberapa sinyal 100 bin yang saya simulasikan dengan Python - agar lebih realistis.
Pada tingkat dasar, pikiran pertama saya adalah pergi bin demi bin dan hanya menghasilkan nomor acak antara kisaran tertentu dan menambah atau mengurangi ini dari sinyal.
Saya berharap (karena ini python) bahwa mungkin ada cara yang lebih cerdas untuk melakukan ini melalui numpy atau sesuatu. (Saya kira idealnya angka yang diambil dari distribusi gaussian dan ditambahkan ke setiap bin akan lebih baik juga.)
Terima kasih sebelumnya atas balasan apa pun.
Saya hanya pada tahap merencanakan kode saya, jadi saya tidak punya apa-apa untuk ditampilkan. Saya hanya berpikir bahwa mungkin ada cara yang lebih canggih untuk menghasilkan kebisingan.
Dari segi output, jika saya memiliki 10 bin dengan nilai berikut:
Bin 1: 1 Bin 2: 4 Bin 3: 9 Bin 4: 16 Bin 5: 25 Bin 6: 25 Bin 7:16 Bin 8: 9 Bin 9: 4 Bin 10: 1
Saya hanya ingin tahu apakah ada fungsi yang telah ditentukan sebelumnya yang dapat menambahkan noise untuk memberi saya sesuatu seperti:
Tempat Sampah 1: 1.13 Kotak 2: 4.21 Kotak 3: 8.79 Kotak 4: 16.08 Kotak 5: 24.97 Kotak 6: 25.14 Kotak 7: 16.22 Kotak 8: 8.90 Kotak 9: 4.02 Kotak 10: 0.91
Jika tidak, saya hanya akan pergi bin-by-bin dan menambahkan nomor yang dipilih dari distribusi gaussian untuk masing-masing.
Terima kasih.
Ini sebenarnya sinyal dari teleskop radio yang saya simulasi. Saya ingin akhirnya dapat memilih sinyal untuk rasio kebisingan simulasi saya.
Jawaban:
Anda dapat menghasilkan derau derau, dan menambahkannya ke sinyal Anda
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
sumber
... Dan bagi mereka yang - seperti saya - sangat awal dalam kurva belajar yang sulit,
import numpy as np pure = np.linspace(-1, 1, 100) noise = np.random.normal(0, 1, 100) signal = pure + noise
sumber
Bagi mereka yang mencoba membuat koneksi antara SNR dan variabel acak normal yang dihasilkan oleh numpy:
[1] , penting untuk diingat bahwa P adalah kekuatan rata - rata .
Atau dalam dB:
[2]
Dalam hal ini, kami sudah memiliki sinyal dan kami ingin menghasilkan derau untuk memberi kami SNR yang diinginkan.
Meskipun derau dapat datang dalam berbagai rasa bergantung pada apa yang Anda modelkan, awal yang baik (terutama untuk contoh teleskop radio ini) adalah Aditif Gaussian Putih Kebisingan (AWGN) . Seperti yang dinyatakan dalam jawaban sebelumnya, untuk memodelkan AWGN Anda perlu menambahkan variabel acak gaussian nol ke sinyal asli Anda. Varians dari variabel acak tersebut akan mempengaruhi kekuatan kebisingan rata - rata .
Untuk variabel acak Gaussian X, kekuatan rata-rata , juga dikenal sebagai momen kedua , adalah
[3]
Jadi untuk white noise, dan daya rata-rata kemudian sama dengan varians .
Saat memodelkan ini dengan python, Anda dapat
1. Menghitung varians berdasarkan SNR yang diinginkan dan serangkaian pengukuran yang ada, yang akan berfungsi jika Anda mengharapkan pengukuran Anda memiliki nilai amplitudo yang cukup konsisten.
2. Sebagai alternatif, Anda dapat mengatur daya derau ke tingkat yang diketahui untuk mencocokkan sesuatu seperti derau penerima. Kebisingan penerima dapat diukur dengan mengarahkan teleskop ke ruang bebas dan menghitung daya rata-rata.
Bagaimanapun, penting untuk memastikan bahwa Anda menambahkan noise ke sinyal Anda dan mengambil rata-rata dalam ruang linier dan bukan dalam unit dB.
Berikut beberapa kode untuk menghasilkan tegangan sinyal dan plot, daya dalam Watt, dan daya dalam 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()
Berikut adalah contoh untuk menambahkan AWGN berdasarkan SNR yang diinginkan:
# 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()
Dan berikut adalah contoh untuk menambahkan AWGN berdasarkan kekuatan derau yang diketahui:
# 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()
sumber
Bagi mereka yang ingin menambahkan noise ke kumpulan data multi-dimensi yang dimuat dalam bingkai data pandas atau bahkan ndarray numpy, berikut ini contohnya:
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 """
sumber
Dalam kehidupan nyata, Anda ingin mensimulasikan sinyal dengan derau putih. Anda harus menambahkan titik acak sinyal yang memiliki distribusi Gaussian Normal. Jika kita berbicara tentang perangkat yang memiliki sensitivitas yang diberikan dalam satuan / SQRT (Hz) maka Anda perlu menyusun deviasi standar poin Anda darinya. Di sini saya memberikan fungsi "white_noise" yang melakukan ini untuk Anda, sisa kode adalah demonstrasi dan memeriksa apakah ia melakukan apa yang seharusnya.
%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()
sumber
Jawaban luar biasa di atas. Saya baru-baru ini memiliki kebutuhan untuk menghasilkan data simulasi dan inilah yang saya gunakan. Berbagi dalam kasus membantu orang lain juga,
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
sumber
AWGN Mirip dengan Fungsi 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
sumber