NumPy中序列的产物

时间:2016-01-09 16:48:52

标签: python arrays numpy multidimensional-array vectorization

我需要使用NumPy实现以下功能 -

enter image description here

其中F_l(x)N我需要计算的数组数,这些数组依赖于数组G(x),我得到了,A_j是{{} 1}}也给出了系数。我想在NumPy中实现它,因为我必须为我的程序的每次迭代计算N。这样做的虚拟方法是for for循环和ifs:

F_l(x)

至于循环和if语句相对较慢,我正在寻找一种NumPy诙谐的方式来做同样的事情。有人有想法吗?

1 个答案:

答案 0 :(得分:2)

本文中列出了一个矢量化解决方案,根据所涉及的计算,在将输入数组的维度扩展到具有NumPy's powerful broadcasting feature的3D和4D情况后,大量使用np.newaxis/None。这是实施 -

# Get size of A
N = A.size

# Perform "(G - A[l])/(G + A[j]))" in a vectorized manner
p1 = (G - A[:,None,None,None])/(G + A[:,None,None])

# Perform "((A[l] - A[j])/(A[l] + A[j]))" in a vectorized manner
p2 = ((A[:,None] - A)/(A[:,None] + A))

# Elementwise multiplications between the previously calculated parts
p3 = p1*p2[...,None,None]

# Set the escaped portion "j != l" output as "G/A[l]"
p3[np.eye(N,dtype=bool)] = G/A[:,None,None]
Fout = p3.prod(1)

# If you need separate arrays just like in the question, split it
Fout_split = np.array_split(Fout,N)

示例运行 -

In [284]: # Original inputs
     ...: A = np.arange(1.,5.,1)
     ...: G = np.array([[1.,2.],[3.,4.]])
     ...: 

In [285]: calcF(G,A)
Out[285]: 
[array([[-0.        , -0.00166667],
        [-0.01142857, -0.03214286]]), array([[-0.00027778,  0.        ],
        [ 0.00019841,  0.00126984]]), array([[  1.26984127e-03,   1.32275132e-04],
        [ -0.00000000e+00,  -7.93650794e-05]]), array([[-0.00803571, -0.00190476],
        [-0.00017857,  0.        ]])]

In [286]: vectorized_calcF(G,A) # Posted solution 
Out[286]: 
[array([[[-0.        , -0.00166667],
         [-0.01142857, -0.03214286]]]), array([[[-0.00027778,  0.        ],
         [ 0.00019841,  0.00126984]]]), array([[[  1.26984127e-03,   1.32275132e-04],
         [ -0.00000000e+00,  -7.93650794e-05]]]), array([[[-0.00803571, -0.00190476],
         [-0.00017857,  0.        ]]])]

运行时测试 -

In [289]: # Larger inputs
     ...: A = np.random.randint(1,500,(400))
     ...: G = np.random.randint(1,400,(20,20))
     ...: 

In [290]: %timeit calcF(G,A)
1 loops, best of 3: 4.46 s per loop

In [291]: %timeit vectorized_calcF(G,A)  # Posted solution 
1 loops, best of 3: 1.87 s per loop

使用NumPy / MATLAB进行矢量化:一般方法

感觉就像我可以在我的一般方法上投入两分钱,我认为其他人在尝试矢量化代码时会遵循类似的策略,特别是在像NumPy或MATLAB这样的高级平台上。所以,这里是Vectorization可以考虑的事项的快速检查清单 -

关于扩展维度的想法:要为输入数组扩展维度,以便新维度保留在嵌套循环中迭代生成的结果。

从哪里开始向量化?从最深处(代码迭代最多的循环)计算阶段开始,看看如何扩展输入并引入相关计算。请仔细跟踪所涉及的迭代器并相应地扩展尺寸。向外移动到外部循环,直到您对完成的矢量化感到满意。

如何处理条件语句?对于简单的情况,暴力计算所有内容并查看以后如何处理IF / ELSE部分。这将是高度针对具体情况的。

是否存在依赖项?如果是,请查看是否可以跟踪和实施相关性。这可以形成另一个讨论主题,但这里是few examples我自己参与其中。