【问题标题】:How to avoid double for loops?如何避免双重for循环?
【发布时间】:2019-05-01 15:16:28
【问题描述】:

我想使用来自其他 2 个矩阵的数据计算 2 个矩阵(内部、外部)的一部分。它们的大小都一样。下面的代码有效,但在大矩阵上太慢了。我在另一种情况下使用了np.fromfunction,但计算的不仅仅是一个子集,而是整个矩阵。

双 for 循环最快的替代方法是什么?

F = np.random.rand(100,100)
S = 10*np.random.rand(100,100) + 1

L,C = F.shape

inner = np.zeros((L,C))
outer = np.zeros((L,C))

for l in range(5, L - 5):
    for c in range(5, C - 5):
        inner[l,c] = np.mean(F[l-5 : l+5 , c-5:c])
        outer[l,c] = np.mean(F[l-5 : l+5 , c+5 : c+5+int(S[l,c])])

【问题讨论】:

    标签: python-3.x numpy for-loop


    【解决方案1】:

    看起来innerF 上的 10x5 平均滤波器卷积的结果。这很容易重写为与scipy 的卷积,并且它将与您从 CPU 获得的一样快。但是,由于您在矩阵的边界上遗漏了 5 行和列,因此您必须相应地截断输出 innerinner2 矩阵以便能够比较它们。

    import numpy as np
    from scipy.signal import convolve2d
    
    F = np.random.rand(100,100)
    S = 10*np.random.rand(100,100) + 1
    
    L,C = F.shape
    
    inner = np.zeros((L,C))
    outer = np.zeros((L,C))
    
    for l in range(5, L - 5):
        for c in range(5, C - 5):
            inner[l, c] = np.mean(F[l-5 : l+5 , c-5:c])
            outer[l, c] = np.mean(F[l-5 : l+5 , c+5 : c+ 5 + int(S[l, c])])
    
    # if inner[l, c] = np.mean(F[l-5 : l+5 , c-5:c+5]),
    # then you should use a 10x10 filter
    avg_filter = np.ones((10, 5)) / (10*5)
    inner2 = convolve2d(F, avg_filter, mode='valid')
    
    # should be very small (1.262e-13 for me)
    print((inner2[:89, :89] - inner[5:94, 5:94]).sum()) 
    

    outer 的表达式很奇怪,因为您在表达式中添加了这个 int(S[l, c]) 偏移量。我认为您不能将其表示为矩阵计算。 因此,要替换您的双 for 循环,您可以使用 from itertools import product 迭代两个可迭代对象的笛卡尔积,如下所示:

    from itertools import product
    
    for (l, c) in product(range(5, L - 5), range(5, C - 5)):
        outer[l, c] = np.mean(F[l-5 : l+5 , c+5 : c+ 5 + int(S[l, c])])
    

    从信号处理的角度来看,我不确定outer 矩阵应该是什么。如果您告诉我们您正在尝试做什么,则更容易编写更快的代码并获得所需的效果。

    【讨论】:

    • F 是一个强度矩阵,S 是一个阴影长度矩阵,它会随着与源的距离增加而随列变化,但也会随行变化,因为高度会随行变化。这个想法是获得两个矩形之间的比率,并为代表对象的矩形和代表阴影的矩形添加一些条件。
    • 好的,我认为你可以通过一个 10x15 的过滤器来处理这种行为,这个过滤器会随着卷积的当前位置而变化,这不是 scipy 可以做到的。如果性能确实是一个问题,那么我建议要么在 Cython 中编写它,要么寻找一些更传统的方式来产生阴影。在这两种情况下,您都必须做一些研究;-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-26
    • 1970-01-01
    相关资源
    最近更新 更多