Aufgrund ihrer Kovarianzmatrix (ihre Leistungsspektraldichten (PSDs) und Kreuzleistungsspektraldichten (CSDs)) habe ich Probleme, eine Reihe stationärer farbiger Zeitreihen zu erstellen.
Ich weiß, dass ich mit zwei Zeitreihen und ihre Leistungsspektraldichten (PSDs) und Kreuzspektraldichten (CSDs) unter Verwendung vieler allgemein verfügbarer Routinen abschätzen kann, wie z und Funktionen in Matlab usw. Die PSDs und CSDs bilden die Kovarianzmatrix:
psd()
csd()
Was passiert, wenn ich das Gegenteil tun möchte? Wie kann ich unter Berücksichtigung der Kovarianzmatrix eine Realisierung von und erzeugen ?
Bitte fügen Sie eine Hintergrundtheorie hinzu oder weisen Sie auf vorhandene Tools hin, die dies tun (alles in Python wäre großartig).
Mein Versuch
Nachstehend finden Sie eine Beschreibung meiner Versuche und der Probleme, die mir aufgefallen sind. Es ist ein bisschen langwierig und es tut mir leid, wenn es Begriffe enthält, die missbraucht wurden. Wenn darauf hingewiesen werden kann, was fehlerhaft ist, wäre dies sehr hilfreich. Aber meine Frage ist die oben fett gedruckte.
- Die PSDs und CSDs können als Erwartungswert (oder Ensemble-Durchschnitt) der Produkte der Fourier-Transformationen der Zeitreihen geschrieben werden. Die Kovarianzmatrix kann also wie geschrieben werden:
wo
- Eine Kovarianzmatrix ist eine Hermitianische Matrix mit reellen Eigenwerten, die entweder Null oder positiv sind. Es kann also zerlegt werden in
wobei ist eine Diagonalmatrix, deren Nicht-Null-Elemente die Quadratwurzeln der Eigenwerte von ; ist die Matrix, deren Spalten die orthonormalen Eigenvektoren von ;ist die Identitätsmatrix.
- Die Identitätsmatrix wird geschrieben als
wobei
und sind unkorrelierte und komplexe Frequenzreihen mit einem Mittelwert von Null und einer Einheitsvarianz.
- Durch Verwenden von 3. in 2. und dann Vergleichen mit 1. Die Fourier-Transformationen der Zeitreihe lauten:
- Die Zeitreihen können dann unter Verwendung von Routinen wie der inversen schnellen Fourier-Transformation erhalten werden.
Ich habe dazu in Python eine Routine geschrieben:
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
Ich habe diese Routine auf PSDs und CSDs angewendet, deren analytische Ausdrücke aus der Modellierung eines Detektors stammen, mit dem ich arbeite. Wichtig ist, dass sie bei allen Frequenzen eine Kovarianzmatrix bilden (zumindest bestehen sie alle diese if
Anweisungen in der Routine). Die Kovarianzmatrix ist 3x3. Die 3 Zeitreihen wurden ungefähr 9000-mal generiert, und die geschätzten PSDs und CSDs, gemittelt über alle diese Realisierungen, sind unten mit den analytischen dargestellt. Während die Gesamtformen einverstanden ist , gibt es spürbare laut Funktionen bei bestimmten Frequenzen in den Zentralverwahrern (Abb.2). Nach einer Nahaufnahme der Peaks in den PSDs (Abb. 3) bemerkte ich, dass die PSDs tatsächlich unterschätzt werdenund dass die Rauschmerkmale in den CSDs bei ungefähr den gleichen Frequenzen auftreten wie die Spitzen in den PSDs. Ich denke nicht, dass dies ein Zufall ist und dass irgendwie Strom aus den PSDs in die CSDs fließt. Ich hätte erwartet, dass die Kurven bei so vielen Erkenntnissen der Daten übereinander liegen.