Jos*_*ngs 6 python numpy vectorization
我如何对这个循环进行矢量化,这个循环使用numpy数组填充更大矩阵的两个正方形子矩阵(也保持更大的矩阵对称):
for x in range(n):
assert m[x].shape == (n,)
M[i:i+n,j+x] = m[x]
M[j+x,i:i+n] = m[x]
Run Code Online (Sandbox Code Playgroud)
这很诱人,但不同意上面的循环(参见下面的示例分歧):
assert m.shape == (n,n)
M[i:i+n,j:j+n] = m
M[j:j+n,i:i+n] = m
Run Code Online (Sandbox Code Playgroud)
这是一个小例子(n> 1崩溃):
from numpy import arange,empty,NAN
from numpy.testing import assert_almost_equal
for n in (1,2,3,4):
# make the submatrix
m = (10 * arange(1, 1 + n * n)).reshape(n, n)
N = n # example below, submatrix is the whole thing
# M1 using loops, M2 "vectorized"
M1 = empty((N, N))
M2 = empty((N, N))
M1.fill(NAN)
M2.fill(NAN)
i,j = 0,0 # not really used when (n == N)
# this results in symmetric matrix
for x in range(n):
assert m[x].shape == (n,)
M1[i:i+n,j+x] = m[x]
M1[j+x,i:i+n] = m[x]
# this does not work as expected
M2[i:i+n,j:j+n] = m
M2[j:j+n,i:i+n] = m
assert_almost_equal(M1,M1.transpose(),err_msg="M not symmetric?")
print "M1\n",M1,"\nM2",M2
assert_almost_equal(M1,M2,err_msg="M1 (loop) disagrees with M2 (vectorized)")
Run Code Online (Sandbox Code Playgroud)
我们最终得到:
M1 = [10 30
30 40] # symmetric
M2 = [10 20
30 40] # i.e. m
Run Code Online (Sandbox Code Playgroud)
您的测试不正确:对于 i,j=0,0 您的 M2[]= 赋值只是覆盖相同的矩阵块。
使用 M1 时获得对称矩阵的原因是您在单个循环中分配 M1 值。
如果你将循环分成两部分:
for x in range(n):
M1[i:i+n,j+x] = m[x]
for x in range(n):
M1[j+x,i:i+n] = m[x]
Run Code Online (Sandbox Code Playgroud)
M1 显然与 M2 相同。
总结一下,以下代码可以工作(相当于您的 M2 计算)但是!仅当对角线上方和下方的块之间没有重叠时,它才会起作用。如果有的话你必须决定在那里做什么
xs=np.arange(4).reshape(2,2)
ys=np.zeros((7,7))
ys[i:i+n,j:j+n]=xs
ys[j:j+n,i:i+n]=xs.T
print ys
>> array([[ 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 1., 0., 0.],
[ 0., 0., 0., 2., 3., 0., 0.],
[ 0., 0., 2., 0., 0., 0., 0.],
[ 0., 1., 3., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0.]])
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6704 次 |
| 最近记录: |