删除for循环以使其更快-numpy



我有这个使用numpy:的python代码

import numpy as np
table = np.array([[23, 54, 12], 
[17, 32, 25],
[43, 19, 11],
[31, 22, 10],
[21, 19, 35]])
r, c = table.shape
out = np.zeros((r,c)) 
out[0, :] = np.cumsum(table[0,:])
out[:, 0] = np.cumsum(table[:,0]) 
for j in range(1, c):
for i in range(1, r):
out[i,j] = max( out[i-1,j], out[i,j-1] ) + table[i,j]
out[-1,-1]

我首先计算数组"out"的第一行和第一列,而其余的值是用for循环中的等式计算的。我只对表的最后一个值感兴趣(out[-1,-1](,我想让它尽可能快。我能以某种方式删除两个for循环吗??

这实际上是在寻找从每个坐标到0,0的最长路径,其中成本由路径上每个节点的表给出。处理此类问题的标准"矩阵方法"是Floy Warshall算法,该算法进行n次矩阵乘法运算,其中n是节点数,在您的情况下为r*c。你的算法实际上已经是Floyd-Warshall的优化变体,它使用了从(i,j(到(0,0(的每条路径都必须通过(i-1,j(或(i,j-1(的事实。

这已经是一个巨大的优化!

我认为如果不在所有坐标上进行迭代,就没有办法解决这个问题。

但也许你可以使用一些图库将其编码为一个图问题,这将把迭代部分推到(高效的(图库中。

更好:

您可以在对角线上迭代,例如使用fill_diagonal。这样,你只会在对角线的数量上迭代。

我不完全确定你想要实现什么。

您正在创建一个新的out数组,该数组复制原始表中的第一(第0(行和列。(顺便说一句,在out[:, 0] = np.cumsum(table[:,0])处,您可以覆盖[0, 0]处的元素(。

然后,通过获取前一行中元素或前一列中元素的最大值,继续填充out数组的其余部分。

然后将该点处原始数组table的内容添加到最大值。

由于您在out数组中查找以前的行和列,您经常会发现自己在检查这些值之前已经覆盖了这些值。例如,当你在i=2, j=1时,你得到了阵列

[[ 23.  77.  89.]
[ 40. 109.   0.]
[ 83.  *?*   0.]
[114.   0.   0.]
[135.   0.   0.]]

你在*?*检查109和83。您刚刚在上一次迭代中插入了109。

因此,如果不使用for循环,就无法获得相同的结果。

最新更新