Kri*_*ten 14 python numpy vectorization
我正在尝试使用NumPy和矢量化操作来使代码段运行得更快.然而,我似乎误解了如何对这段代码进行矢量化(可能是由于对矢量化的理解不完全).
这是带循环的工作代码(A和B是已设置大小的2D数组,已经初始化):
for k in range(num_v):
B[:] = A[:]
for i in range(num_v):
for j in range(num_v):
A[i][j] = min(B[i][j], B[i][k] + B[k][j])
return A
Run Code Online (Sandbox Code Playgroud)
这是我尝试矢量化上面的代码:
for k in range(num_v):
B = numpy.copy(A)
A = numpy.minimum(B, B[:,k] + B[k,:])
return A
Run Code Online (Sandbox Code Playgroud)
为了测试这些,我使用了以下代码,上面的代码包含在一个名为'algorithm'的函数中:
def setup_array(edges, num_v):
r = range(1, num_v + 1)
A = [[None for x in r] for y in r] # or (numpy.ones((num_v, num_v)) * 1e10) for numpy
for i in r:
for j in r:
val = 1e10
if i == j:
val = 0
elif (i,j) in edges:
val = edges[(i,j)]
A[i-1][j-1] = val
return A
A = setup_array({(1, 2): 2, (6, 4): 1, (3, 2): -3, (1, 3): 5, (3, 6): 5, (4, 5): 2, (3, 1): 4, (4, 3): 8, (3, 4): 6, (2, 4): -4, (6, 5): -5}, 6)
B = []
algorithm(A, B, 6)
Run Code Online (Sandbox Code Playgroud)
预期的结果,以及我得到的第一个代码是:
[[0, 2, 5, -2, 0, 10]
[8, 0, 4, -4, -2, 9]
[4, -3, 0, -7, -5, 5]
[12, 5, 8, 0, 2, 13]
[10000000000.0, 9999999997.0, 10000000000.0, 9999999993.0, 0, 10000000000.0]
[13, 6, 9, 1, -5, 0]]
Run Code Online (Sandbox Code Playgroud)
第二个(矢量化)函数返回:
[[ 0. -4. 0. 0. 0. 0.]
[ 0. -4. 0. -4. 0. 0.]
[ 0. -4. 0. 0. 0. 0.]
[ 0. -4. 0. 0. 0. 0.]
[ 0. -4. 0. 0. 0. 0.]
[ 0. -4. 0. 0. -5. 0.]]
Run Code Online (Sandbox Code Playgroud)
我错过了什么?
The*_*eke 14
通常,您希望对代码进行矢量化,因为您认为代码运行速度太慢.
如果您的代码太慢,那么我可以告诉您正确的索引将使它更快.
而不是A[i][j]你应该写A[i, j]- 这避免了(子)数组的瞬态副本.
由于您在代码的最内层循环中执行此操作,因此这可能非常昂贵.
看这里:
In [37]: timeit test[2][2]
1000000 loops, best of 3: 1.5 us per loop
In [38]: timeit test[2,2]
1000000 loops, best of 3: 639 ns per loop
Run Code Online (Sandbox Code Playgroud)
在您的代码中始终如一地这样做 - 我坚信这已经解决了您的性能问题!
话说回来...
for k in range(num_v):
numpy.minimum(A, np.add.outer(A[:,k], A[k,:]), A)
return A
Run Code Online (Sandbox Code Playgroud)
numpy.minimum将比较两个数组并返回元素两个元素中较小的一个.如果你传递第三个参数,它将获取输出.如果这是一个输入数组,则整个操作就位.
正如Peter de Rivay解释的那样,你的广播解决方案存在问题 - 但在数学上你想要做的是通过添加两个向量来获得某种外部产品.因此,您可以在add函数上使用外部操作.
NumPy的二进制ufuncs具有执行某些特殊向量化操作的特殊方法,如reduce,accumulate,sum和outer.
Pet*_*vaz 11
该问题是由行中的阵列广播引起的:
A = numpy.minimum(B, B[:,k] + B[k,:])
Run Code Online (Sandbox Code Playgroud)
B的大小为6乘6,B [:,k]是具有6个元素的数组,B [k,:]是具有6个元素的数组.
(因为你使用的是numpy数组类型,B [:,k]和B [k,:]都返回一个形状为N的rank-1数组
Numpy自动更改大小以匹配:
这意味着你的numpy代码相当于:
for k in range(num_v):
B[:] = A[:]
C=[B[i][k]+B[k][i] for i in range(num_v)]
for i in range(num_v):
for j in range(num_v):
A[i][j] = min(B[i][j], C[j])
Run Code Online (Sandbox Code Playgroud)
修复代码的最简单方法是使用矩阵类型而不是数组类型:
A = numpy.matrix(A)
for k in range(num_v):
A = numpy.minimum(A, A[:,k] + A[k,:])
Run Code Online (Sandbox Code Playgroud)
矩阵类型使用更严格的广播规则,因此在这种情况下:
| 归档时间: |
|
| 查看次数: |
14170 次 |
| 最近记录: |