【问题标题】:Python: Efficienctly calculate mean of off-diagonal elements for Cadzow filterPython:有效地计算 Cadzow 滤波器的非对角线元素的平均值
【发布时间】:2018-05-04 13:03:53
【问题描述】:

我目前在 Python 中实现了一个 Gadzow 过滤器。

在某些情况下。您从一个一维数组开始(我们以 range(10) 为例)并从中构建一个类似 Hankel 的矩阵

H= [[0, 1, 2, 3, 4, 5],
    [1, 2, 3, 4, 5, 6],
    [2, 3, 4, 5, 6, 7],
    [3, 4, 5, 6, 7, 8],
    [4, 5, 6, 7, 8, 9]])

然后你用这个矩阵做一些线性代数,这没问题。之后,最耗时的步骤是平均问题。

在一个新的矩阵 B 中,你平均得到的矩阵的元素。在第一行中,您通过 H 中的精度给出的路径对所有元素进行平均。所以类似于非对角线,但从右上角到左下角。在第二个切片中,您忽略第一行,依此类推。

矩阵 $H$ 在此分析步骤下将保持不变,但例如矩阵

1 2 2 1
1 1 1 1
1 1 1 1

会变成

1 1.5 1.33 1
1 1   1    1
1 1   1    1

好的,我希望你明白这个问题。我的(工作但效率低下)代码是

def av_diag(A,i,j):
    dim = A.shape
    # get the "borders" of A
    lim = min((dim[0]-i,j+1))
    # calculate the mean
    return np.mean([A[i+it,j-it] for it in range(lim)])

def avHankel(A):
    # get the mean for all elements by nested list comprehension
    return np.array([[av_diag(A,i,j) for j in range(len(A[0]))] for i in range(len(A))]) 

我的数据需要一段时间,包含 2048 个数据点,生成 1024x1023 矩阵。

我很高兴能有一些技巧来加快速度。

谢谢

【问题讨论】:

    标签: python performance filter data-processing


    【解决方案1】:

    您可以将输入矩阵与 过滤器 矩阵进行卷积,以加快您的代码速度。可以定义 filter 矩阵,以便在卷积的每个步骤中,它只提取给定坐标处的对角线。基本上,您的 filter 矩阵只是一个反恒等矩阵。最后,由于卷积只会对反对角线的元素求和,因此您必须将输出除以正确的样本数以获得均值:

    import numpy as np
    from scipy.signal import fftconvolve
    from time import time
    
    
    def av_diag(A,i,j):
        dim = A.shape
        lim = min((dim[0]-i,j+1))
        return np.mean([A[i+it,j-it] for it in range(lim)])
    
    def avHankel(A):
        return np.array([[av_diag(A,i,j) for j in range(len(A[0]))] for i in range(len(A))])
    
    
    def fast_avHankel(A):
        m, n = A.shape
        filt = np.eye(m)[:,::-1]
        Apad = np.pad(A, ((0, m-1), (m-1, 0)), mode = "constant", constant_values = 0)
        Asum = fftconvolve(Apad, filt, mode = "valid")
        Adiv = np.array([ [ min(m-i, j+1) for j in range(n) ] for i in range(m) ])
        return Asum / Adiv
    
    
    if __name__ == "__main__":
        A = np.random.rand(500, 500)
    
        starttime = time()
        Hold = avHankel(A)
        print(time() - starttime)    # 10.6 seconds on a laptop
    
        starttime = time()
        Hnew = fast_avHankel(A)
        print(time() - starttime)    # 0.26 seconds on a laptop
    

    【讨论】:

    • 这看起来不错,我得好好想想,你在做什么,不过非常感谢
    猜你喜欢
    • 2020-09-26
    • 1970-01-01
    • 2017-09-10
    • 1970-01-01
    • 1970-01-01
    • 2018-02-18
    • 1970-01-01
    • 2017-12-19
    • 1970-01-01
    相关资源
    最近更新 更多