Saya mengalami masalah dalam menghasilkan serangkaian seri waktu berwarna stasioner, mengingat matriks kovariansnya (densitas spektral daya (PSD)) dan densitas spektral cross-power (CSD)).
Saya tahu bahwa, mengingat dua seri waktu dan , saya dapat memperkirakan kepadatan spektral daya (PSD) dan kepadatan spektral silang (CSD) menggunakan banyak rutinitas yang tersedia secara luas, seperti psd()
dan csd()
fungsi dalam Matlab , dll. PSD dan CSD membentuk matriks kovarian:
Apa yang terjadi jika saya ingin melakukan yang sebaliknya? Mengingat matriks kovarians, bagaimana cara menghasilkan realisasi dan ?
Harap sertakan teori latar belakang apa pun, atau tunjukkan alat yang ada yang melakukan ini (apa pun dengan Python akan bagus).
Usaha saya
Di bawah ini adalah deskripsi dari apa yang saya coba, dan masalah yang saya perhatikan. Ini agak lama dibaca, dan maaf jika mengandung istilah yang telah disalahgunakan. Jika apa yang salah dapat ditunjukkan, itu akan sangat membantu. Tetapi pertanyaan saya adalah yang dicetak tebal di atas.
- PSD dan CSD dapat ditulis sebagai nilai ekspektasi (atau rata-rata ensemble) dari produk-produk dari transformasi Fourier dari deret waktu. Jadi, matriks kovarians dapat ditulis sebagai:
mana
- Matriks kovarians adalah matriks Hermitian, yang memiliki nilai eigen nyata yang nol atau positif. Jadi, ini dapat didekomposisi menjadi
mana adalah matriks diagonal yang unsur-unsurnya bukan nol adalah akar kuadrat dari nilai eigen ; adalah matriks yang kolomnya adalah vektor eigen ortonormal dari ;adalah matriks identitas.
- Matriks identitas ditulis sebagai
mana
dan tidak berkorelasi dan seri-frekuensi kompleks dengan nol rata-rata dan varians unit.
- Dengan menggunakan 3. pada 2., dan kemudian membandingkan dengan 1. Transformasi Fourier dari deret waktu adalah:
- Rangkaian waktu kemudian dapat diperoleh dengan menggunakan rutinitas seperti transformasi Fourier cepat terbalik.
Saya telah menulis rutin dalam Python untuk melakukan ini:
def get_noise_freq_domain_CovarMatrix( comatrix , df , inittime , parityN , seed='none' , N_previous_draws=0 ) :
"""
returns the noise time-series given their covariance matrix
INPUT:
comatrix --- covariance matrix, Nts x Nts x Nf numpy array
( Nts = number of time-series. Nf number of positive and non-Nyquist frequencies )
df --- frequency resolution
inittime --- initial time of the noise time-series
parityN --- is the length of the time-series 'Odd' or 'Even'
seed --- seed for the random number generator
N_previous_draws --- number of random number draws to discard first
OUPUT:
t --- time [s]
n --- noise time-series, Nts x N numpy array
"""
if len( comatrix.shape ) != 3 :
raise InputError , 'Input Covariance matrices must be a 3-D numpy array!'
if comatrix.shape[0] != comatrix.shape[1] :
raise InputError , 'Covariance matrix must be square at each frequency!'
Nts , Nf = comatrix.shape[0] , comatrix.shape[2]
if parityN == 'Odd' :
N = 2 * Nf + 1
elif parityN == 'Even' :
N = 2 * ( Nf + 1 )
else :
raise InputError , "parityN must be either 'Odd' or 'Even'!"
stime = 1 / ( N*df )
t = inittime + stime * np.arange( N )
if seed == 'none' :
print 'Not setting the seed for np.random.standard_normal()'
pass
elif seed == 'random' :
np.random.seed( None )
else :
np.random.seed( int( seed ) )
print N_previous_draws
np.random.standard_normal( N_previous_draws ) ;
zs = np.array( [ ( np.random.standard_normal((Nf,)) + 1j * np.random.standard_normal((Nf,)) ) / np.sqrt(2)
for i in range( Nts ) ] )
ntilde_p = np.zeros( ( Nts , Nf ) , dtype=complex )
for k in range( Nf ) :
C = comatrix[ :,:,k ]
if not np.allclose( C , np.conj( np.transpose( C ) ) ) :
print "Covariance matrix NOT Hermitian! Unphysical."
w , V = sp_linalg.eigh( C )
for m in range( w.shape[0] ) :
w[m] = np.real( w[m] )
if np.abs(w[m]) / np.max(w) < 1e-10 :
w[m] = 0
if w[m] < 0 :
print 'Negative eigenvalue! Simulating unpysical signal...'
ntilde_p[ :,k ] = np.conj( np.sqrt( N / (2*stime) ) * np.dot( V , np.dot( np.sqrt( np.diag( w ) ) , zs[ :,k ] ) ) )
zerofill = np.zeros( ( Nts , 1 ) )
if N % 2 == 0 :
ntilde = np.concatenate( ( zerofill , ntilde_p , zerofill , np.conj(np.fliplr(ntilde_p)) ) , axis = 1 )
else :
ntilde = np.concatenate( ( zerofill , ntilde_p , np.conj(np.fliplr(ntilde_p)) ) , axis = 1 )
n = np.real( sp.ifft( ntilde , axis = 1 ) )
return t , n
Saya telah menerapkan rutin ini untuk PSD dan CSD, ekspresi analitik yang telah diperoleh dari pemodelan beberapa detektor yang saya kerjakan. Yang penting adalah bahwa pada semua frekuensi, mereka membentuk matriks kovarians (setidaknya mereka melewati semua if
pernyataan itu dalam rutinitas). Matriks kovarians adalah 3x3. Seri-3 waktu telah dihasilkan sekitar 9000 kali, dan perkiraan PSD dan CSD, dirata-rata untuk semua realisasi ini diplot di bawah ini dengan yang analitis. Sementara bentuk keseluruhan setuju, ada fitur berisik yang terlihat pada frekuensi tertentu di CSD (Gbr.2). Setelah close-up di sekitar puncak di PSD (Gbr.3), saya perhatikan bahwa PSD sebenarnya diremehkan, dan bahwa fitur bising di CSD terjadi pada frekuensi yang hampir sama dengan puncak di PSD. Saya tidak berpikir bahwa ini adalah kebetulan, dan entah bagaimana kekuatan bocor dari PSD ke CSD. Saya berharap kurva berada di atas satu sama lain, dengan banyak realisasi data.