Simulazione di serie storiche date potenza e densità spettrali incrociate


20

Ho difficoltà a generare una serie di serie temporali colorate stazionarie, data la loro matrice di covarianza (densità di potenza spettrale (PSD) e densità spettrale di potenza incrociata (CSD)).

So che, date due serie temporali e , posso stimare la loro densità spettrale di potenza (PSD) e densità spettrale incrociata (CSD) utilizzando molte routine ampiamente disponibili, come ad esempio e funzioni in Matlab, ecc. I PSD e CSD compongono la matrice di covarianza: yio(t)yJ(t)psd()csd()

C(f)=(Pioio(f)PioJ(f)PJio(f)PJJ(f)),
f che è in generale una funzione della frequenza . f

Cosa succede se voglio fare il contrario? Data la matrice di covarianza, come posso generare una realizzazione di e ?yio(t)yJ(t)

Ti preghiamo di includere qualsiasi teoria di base o di evidenziare eventuali strumenti esistenti che lo fanno (qualsiasi cosa in Python sarebbe eccezionale).

Il mio tentativo

Di seguito è una descrizione di ciò che ho provato e dei problemi che ho notato. È un po 'lungo e mi dispiace se contiene termini che sono stati usati in modo improprio. Se si può sottolineare ciò che è errato, ciò sarebbe molto utile. Ma la mia domanda è quella in grassetto sopra.

  1. I PSD e i CSD possono essere scritti come valore di aspettativa (o media dell'insieme) dei prodotti delle trasformate di Fourier delle serie temporali. Quindi, la matrice di covarianza può essere scritta come: dove
    C(f)=2τY(f)Y(f),
    Y(f)=(y~io(f)y~J(f)).
  2. Una matrice di covarianza è una matrice eremitica, con autovalori reali che sono zero o positivi. Quindi, può essere scomposto in
    C(f)=X(f)λ12(f)ioλ12(f)X(f),
    dove λ12(f) è una matrice diagonale i cui elementi diversi da zero sono le radici quadrate degli autovalori di C(f) ; X(f) è la matrice le cui colonne sono gli autovettori ortogonali di C(f) ;io è la matrice identità.
  3. La matrice identità è scritta come dove e sono serie di frequenze non correlate e complesse con media zero e varianza unitaria.
    io=z(f)z(f),
    z(f)=(zio(f)zJ(f)),
    {zio(f)}io=io,J
  4. Usando 3. in 2., quindi confrontandolo con 1. Le trasformazioni di Fourier delle serie temporali sono:
    Y(f)=τ2z(f)λ12(f)X(f).
  5. Le serie temporali possono quindi essere ottenute usando routine come la trasformata di Fourier veloce inversa.

Ho scritto una routine in Python per fare questo:

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

Ho applicato questa routine a PSD e CSD, le cui espressioni analitiche sono state ottenute dalla modellazione di alcuni rivelatori con cui sto lavorando. L'importante è che a tutte le frequenze, formino una matrice di covarianza (beh almeno passano tutte quelle ifaffermazioni nella routine). La matrice di covarianza è 3x3. Le 3 serie temporali sono state generate circa 9000 volte e i PSD e CSD stimati, calcolati in media su tutte queste realizzazioni, sono riportati di seguito con quelli analitici. Mentre le forme complessive concordano, ci sono notevoli caratteristiche rumorose a determinate frequenze nei CSD (Fig.2). Dopo un primo piano attorno ai picchi dei PSD (Fig.3), ho notato che i PSD sono in realtà sottovalutatie che le caratteristiche rumorose nei CSD si verificano quasi alle stesse frequenze dei picchi nei PSD. Non penso che questa sia una coincidenza e che in qualche modo il potere stia perdendo dai PSD ai CSD. Mi sarei aspettato che le curve si trovassero l'una sopra l'altra, con così tante realizzazioni dei dati.

Figura 1: P11
Figura 2: P12 Figura 2: P11 (primo piano)


Benvenuti nel sito. Ho votato a favore di questa domanda, in parte, in modo da non poter pubblicare immagini. In caso contrario, pubblica semplicemente i link e qualcuno con la reputazione sufficiente modificherà per incorporare le immagini.
cardinale il

1
Hai provato a filtrare il rumore ad alta frequenza?
Carl,

Risposte:


1

Poiché i tuoi segnali sono stazionari, un approccio semplice sarebbe quello di utilizzare il rumore bianco come base e filtrarlo per adattarlo ai tuoi PSD. Un modo per calcolare questi coefficienti di filtro consiste nell'utilizzare la previsione lineare .

Sembra che ci sia una funzione Python, provalo:

from scikits.talkbox import lpc

Se vuoi (ho usato solo l'equivalente MATLAB). Questo è un approccio utilizzato nell'elaborazione del parlato, in cui i formanti sono stimati in questo modo.


Non intendi applicare il filtro al segnale piuttosto che al rumore bianco?
Michael R. Chernick,

No, ciò a cui sto puntando è approssimare un filtro in cui la funzione di trasferimento assomigli al PSD di un processo stazionario. Se il rumore bianco, che ha la stessa potenza in tutte le bande di frequenza, viene filtrato con questi, l'uscita assomiglia in modo ottimale ai segnali originali nella sua densità spettrale di potenza.
Jonas Schwarz,

0

Un po 'tardi alla festa, come al solito, ma vedo alcune attività recenti, quindi farò i miei due yen.

Innanzitutto, non posso criticare il tentativo di OP: mi sembra giusto. Le discrepanze potrebbero essere dovute a problemi con campioni finiti, ad esempio la distorsione positiva della stima della potenza del segnale.

Tuttavia, penso che ci siano modi più semplici per generare serie temporali dalla matrice di densità spettrale incrociata (CPSD, questo è ciò che l'OP ha chiamato matrice di covarianza).

Un approccio parametrico consiste nell'utilizzare il CPSD per ottenere una descrizione autoregressiva e quindi utilizzarla per generare le serie temporali. In matlab puoi farlo usando gli strumenti di causalità di Granger (ad esempio Casella degli strumenti di causalità di Granger Multivaraite, Seth, Barnett ). La cassetta degli attrezzi è molto facile da usare. Poiché l'esistenza del CPSD garantisce una descrizione autoregressiva questo approccio è esatto. (per ulteriori informazioni sul CPSD e sull'autoregressione, consultare "Misurazione della dipendenza lineare e feedback tra più serie temporali" di Geweke, 1982, o molti dei documenti Aneil Seth + Lionel Barnett, per ottenere il quadro completo).

Potenzialmente più semplice, sta notando che il CPSD può essere formato applicando il fft all'auto covarianza (dando la diagonale del CPSD, cioè la potenza dei segnali) e la covarianza incrociata (dando gli elementi diagonali off, cioè la potenza incrociata). Quindi, applicando l'inverso fft al CPSD, possiamo ottenere l'autocorrelazione e la covarianza automatica. Possiamo quindi usarli per generare campioni dei nostri dati.

Spero che sia di aiuto. Si prega di lasciare eventuali richieste di informazioni nei commenti e proverò a rispondere.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.