Symulowanie szeregów czasowych przy danej mocy i gęstościach widm poprzecznych

20

Mam problem z wygenerowaniem zestawu stacjonarnych kolorowych szeregów czasowych, biorąc pod uwagę ich macierz kowariancji (ich gęstości widmowe mocy (PSD) i gęstości widmowe mocy krzyżowej (CSD)).

Wiem, że biorąc pod uwagę dwie serie czasowe i , mogę oszacować ich gęstość widmową mocy (PSD) i gęstość krzyżową widmową (CSD) przy użyciu wielu powszechnie dostępnych procedur, takich jak i funkcje w Matlabie itp. PSD i CSD tworzą macierz kowariancji: yja(t)yjot(t)psd()csd()

do(fa)=(P.jaja(fa)P.jajot(fa)P.jotja(fa)P.jotjot(fa)),
f który jest generalnie funkcją częstotliwości . fa

Co się stanie, jeśli chcę zrobić odwrotnie? Biorąc pod uwagę macierz kowariancji, jak wygenerować realizację i ?yja(t)yjot(t)

Podaj dowolną teorię tła lub wskaż istniejące narzędzia, które to robią (wszystko w Pythonie byłoby świetne).

Moja próba

Poniżej znajduje się opis tego, czego próbowałem i problemów, które zauważyłem. Jest to trochę długa lektura i przepraszam, jeśli zawiera warunki, które zostały niewłaściwie użyte. Jeśli można wskazać, co jest błędne, byłoby to bardzo pomocne. Ale moje pytanie jest pogrubione powyżej.

  1. PSD i CSD można zapisać jako wartość oczekiwaną (lub średnią zespoloną) produktów przekształceń Fouriera szeregów czasowych. Tak więc macierz kowariancji można zapisać jako: gdzie
    do(fa)=2)τY(fa)Y(fa),
    Y(fa)=(y~ja(fa)y~jot(fa)).
  2. Macierz kowariancji jest macierzą hermitowską, mającą rzeczywiste wartości własne, które są zerowe lub dodatnie. Można go więc rozłożyć na gdzie jest macierzą diagonalną, której niezerowe elementy są pierwiastkami kwadratowymi wartości własnych \ mathbf {C} (f) ; \ mathbf {X} (f) jest macierzą, której kolumny są ortonormalnymi wektorami własnymi \ mathbf {C} (f) ;
    do(fa)=X(fa)λ12)(fa)jaλ12)(fa)X(fa),
    λ12)(fa)do(fa)X(fa)do(fa)ja to macierz tożsamości.
  3. Macierz tożsamości jest zapisywana jako gdzie i to nieskorelowane i złożone szeregi częstotliwości o zerowej średniej i wariancji jednostkowej.
    ja=z(fa)z(fa),
    z(fa)=(zja(fa)zjot(fa)),
    {zja(fa)}ja=ja,jot
  4. Używając 3. w 2., a następnie porównaj z 1. Transformaty Fouriera szeregów czasowych to:
    Y(fa)=τ2)z(fa)λ12)(fa)X(fa).
  5. Szeregi czasowe można następnie uzyskać za pomocą procedur takich jak odwrotna szybka transformata Fouriera.

Napisałem procedurę w Pythonie, aby to zrobić:

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

Zastosowałem tę procedurę do PSD i CSD, których analityczne wyrażenia zostały uzyskane z modelowania jakiegoś detektora, z którym pracuję. Ważną rzeczą jest to, że przy wszystkich częstotliwościach tworzą one macierz kowariancji (przynajmniej przynajmniej przekazują wszystkie te ifrutynowe czynności). Macierz kowariancji wynosi 3x3. 3 szeregi czasowe wygenerowano około 9000 razy, a szacowane PSD i CSD, uśrednione dla wszystkich tych realizacji, są przedstawione poniżej z analitycznymi. Chociaż ogólne kształty są zgodne, w CDPW zauważalne są hałaśliwe funkcje przy określonych częstotliwościach (ryc. 2). Po zbliżeniu wokół szczytów na PSD (ryc. 3) zauważyłem, że PSD są w rzeczywistości niedocenianeoraz że hałaśliwe funkcje w dyskach CSD występują prawie w przybliżeniu na tych samych częstotliwościach, co szczyty w dyskach PSD. Nie sądzę, że to zbieg okoliczności i że w jakiś sposób moc wycieka z PSD do CSD. Spodziewałbym się, że krzywe leżą jeden na drugim, przy tak wielu realizacjach danych.

Ryc. 1: P11
Rycina 2: P12 Ryc. 2: P11 (zbliżenie)

jestem żonaty
źródło
Witamy na stronie. Głosowałem częściowo nad tym pytaniem, abyście nie mogli publikować zdjęć. Jeśli nie, po prostu opublikuj linki, a osoba o odpowiedniej reputacji będzie edytować, aby osadzić obrazy.
kardynał
1
Czy próbowałeś odfiltrować szum o wysokiej częstotliwości?
Carl

Odpowiedzi:

1

Ponieważ sygnały są nieruchome, prostym podejściem byłoby wykorzystanie białego szumu jako podstawy i przefiltrowanie go, aby pasował do PSD. Sposobem na obliczenie tych współczynników filtrowania jest zastosowanie prognozy liniowej .

Wygląda na to, że istnieje dla niego funkcja python, wypróbuj:

from scikits.talkbox import lpc

Jeśli chcesz (użyłem tylko odpowiednika MATLAB). Jest to podejście stosowane w przetwarzaniu mowy, w którym formanty są szacowane w ten sposób.

Jonas Schwarz
źródło
Czy nie chodzi o zastosowanie filtra do sygnału, a nie do białego szumu?
Michael R. Chernick
Nie, moim celem jest zbliżenie filtra, w którym funkcja przesyłania przypomina PSD procesu stacjonarnego. Jeżeli szumy białe, które mają tę samą moc we wszystkich pasmach częstotliwości, są filtrowane za ich pomocą, sygnał wyjściowy optymalnie przypomina oryginalne sygnały pod względem gęstości widmowej mocy.
Jonas Schwarz
0

Trochę za późno na imprezę, jak zwykle, ale widzę trochę niedawnej aktywności, więc będę miał dwa jeny.

Po pierwsze, nie mogę winić próby OP - wygląda mi to dobrze. Rozbieżności mogą być spowodowane problemami ze skończonymi próbkami, na przykład dodatnim błędem oszacowania mocy sygnału.

Myślę jednak, że istnieją prostsze sposoby generowania szeregów czasowych z macierzy gęstości widma krzyżowego (CPSD, to właśnie OP nazywa macierzą kowariancji).

Jednym podejściem parametrycznym jest użycie CPSD w celu uzyskania opisu autoregresji, a następnie użycie go do wygenerowania szeregów czasowych. W Matlab możesz to zrobić za pomocą narzędzi przyczynowości Grangera (np. Multivaraite Granger Causality Toolbox, Seth, Barnett ). Zestaw narzędzi jest bardzo łatwy w użyciu. Ponieważ istnienie CPSD gwarantuje autoregresyjny opis, podejście to jest dokładne. (aby uzyskać więcej informacji na temat CPSD i autoregresji, patrz „Pomiar zależności liniowej i sprzężenie zwrotne między szeregami czasowymi” Geweke, 1982 lub wiele artykułów Aneil Seth + Lionel Barnett, aby uzyskać pełny obraz).

Potencjalnie prościej jest zauważyć, że CPSD można utworzyć, stosując fft do automatycznej kowariancji (podając przekątną CPSD, tj. Moc sygnałów) i kowariancję krzyżową (podając elementy przekątne, tj. Moc krzyżową). Zatem poprzez zastosowanie odwrotnego fft do CPSD możemy uzyskać autokorelację i automatyczną kowariancję. Następnie możemy je wykorzystać do wygenerowania próbek naszych danych.

Mam nadzieję że to pomoże. Proszę zostawić wszelkie prośby o informacje w komentarzach, a ja postaram się odpowiedzieć.

dcneuro
źródło