模拟给定功率和互谱密度的时间序列


20

给定它们的协方差矩阵(它们的功率谱密度(PSD)和交叉功率谱密度(CSD)),我很难生成一组固定的彩色时间序列。

我知道,给定两个时间序列和,我可以使用许多广泛使用的例程来估算其功率谱密度(PSD)和交叉谱密度(CSD)。和Matlab等中的功能。PSD和CSD组成协方差矩阵: yI(t)yJ(t)psd()csd()

C(f)=(PII(f)PIJ(f)PJI(f)PJJ(f)),
,通常是频率的函数。 f

如果我想做相反的事情怎么办? 给定协方差矩阵,如何生成和y_ {J}(t)的实现yI(t)yJ(t)

请包括任何背景理论,或指出执行此操作的任何现有工具(Python中的任何工具都很好)。

我的尝试

以下是我尝试过的内容以及我注意到的问题的描述。本书读了很长一段时间,如果其中包含误用的术语,则抱歉。如果可以指出错误的地方,那将非常有帮助。但是我的问题是上面的粗体字。

  1. PSD和CSD可以写为时间序列傅立叶变换的乘积的期望值(或整体平均值)。因此,协方差矩阵可以表示为:
    C(f)=2τY(f)Y(f),
    其中
    ÿF=ÿ一世FÿĴF
  2. 协方差矩阵是Hermitian矩阵,其实特征值可以为零或为正。因此,可以将其分解为
    CF=XFλ1个2F一世λ1个2FXF
    其中λ1个2F是一个对角矩阵,其非零元素是CF特征值的平方根;XF是矩阵,其列是CF的正交特征向量;一世是单位矩阵。
  3. 单位矩阵写为 其中 和是不相关且复杂的频率序列,均值和单位方差为零。
    一世=žFžF
    žF=ž一世FžĴF
    {ž一世F}一世=一世Ĵ
  4. 通过在2中使用3.,然后与1比较。时间序列的傅立叶变换为:
    ÿF=τ2žFλ1个2FXF
  5. 然后可以通过使用诸如快速傅立叶逆变换之类的例程来获得时间序列。

我已经用Python编写了一个例程来做到这一点:

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

我已将此例程应用于PSD和CSD,其解析表达式是从我正在使用的某些检测器的建模中获得的。重要的是,它们在所有频率上都构成一个协方差矩阵(至少它们if在例程中传递了所有这些语句)。协方差矩阵为3x3。这三个时间序列已生成约9000次,下面将所有这些实现的平均PSD和CSD估计值与分析性实现一起绘制。虽然总体形状一致,但在CSD中的某些频率上存在明显的噪声特征(图2)。在PSD的峰附近进行了特写(图3)之后,我注意到PSD的确被低估了,并且CSD中的噪声特征出现的频率与PSD中的峰值几乎相同。我不认为这是一个巧合,而是电源从PSD泄漏到CSD中。通过数据的如此众多的实现,我本来可以期望这些曲线相互重叠。

图1:P11
图2:P12 图2:P11(特写)


欢迎来到该网站。我已部分投票赞成该问题,因此您不应发布图像。如果没有,只需发布​​链接,具有足够声誉的人将进行编辑以嵌入图像。
主教

1
您是否尝试过滤除高频噪声?
卡尔

Answers:


1

由于您的信号是固定的,因此一种简单的方法是使用白噪声作为基础,并对其进行滤波以适合您的PSD。计算这些滤波器系数的一种方法是使用线性预测

似乎有一个python函数,请尝试一下:

from scikits.talkbox import lpc

如果您愿意(我只使用过MATLAB的同类产品)。这是语音处理中使用的一种方法,其中以这种方式估计共振峰。


您是不是要对信号而不是白噪声应用滤波器?
Michael R. Chernick

不,我的目标是近似一个滤波器,其中传递函数类似于固定过程的PSD。如果在所有频带上具有相同功率的白噪声被这些滤波器滤除,则输出在其功率谱密度上与原始信号最佳相似。
乔纳斯·施瓦茨

0

和往常一样,聚会晚了一点,但我看到最近有一些活动,所以我要两日元。

首先,我不能指责操作人员的尝试-在我看来,这是对的。差异可能是由于有限样本的问题所致,例如信号功率估计的正偏差。

但是,我认为有更简单的方法可以从交叉谱密度矩阵(CPSD,这就是OP称为协方差矩阵)生成时间序列。

一种参数化方法是使用CPSD获得自回归描述,然后使用该描述生成时间序列。在matlab中,您可以使用Granger因果关系工具(例如Multivaraite Granger因果关系工具箱,Seth,Barnett)进行此操作。该工具箱非常易于使用。由于CPSD的存在保证了自回归描述,因此这种方法是准确的。(有关CPSD和自回归的更多信息,请参阅Geweke于1982年发表的“测量多个时间序列之间的线性相关性和反馈”,或获得Aneil Seth + Lionel Barnett的许多论文,以获得完整的图像)。

可能会更简单,请注意,可以通过将fft应用于自协方差(给出CPSD的对角线,即信号的功率)和交叉协方差(给出非对角线元素,即交叉功率)来形成CPSD。因此,通过将逆fft应用于CPSD,我们可以获得自相关和自协方差。然后,我们可以使用它们来生成数据样本。

希望这可以帮助。请在评论中留下任何信息请求,我将尽力解决。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.