我喜欢numpy因为它允许矢量化操作,例如:
mat1 = np.array([[1,2],[3,4]])
mat2 = np.array([[10,20],[30,40]])
mat3 = (mat1 + mat2)*2.0 # vectorization way. nice.
但是,我找不到如何用对角线元素进行这种操作。我想做的是
是否可以使用numpy以矢量化方式在上面进行操作?
答案 0 :(得分:1)
对于第一个例子:
使用:
In [3]: A
"""
array([[1, 3, 4, 0, 4],
[2, 3, 3, 3, 0],
[1, 0, 4, 1, 0],
[0, 3, 3, 2, 0],
[2, 1, 0, 3, 2]])
"""
In [4]: Aii=vstack((diag(A),)*A.shape[0])
"""
array([[1, 3, 4, 2, 2],
[1, 3, 4, 2, 2],
[1, 3, 4, 2, 2],
[1, 3, 4, 2, 2],
[1, 3, 4, 2, 2]])
"""
In [5]: Ajj=Aii.T # transpose
In [6]: B= 1/ (Aii+Ajj-2*A)
或者,使用更抽象的工具:
B1 = 1 / (np.add.outer(diag(A),diag(A))-2*A)
B2 = A / np.sqrt(np.multiply.outer(diag(A),diag(A)))
答案 1 :(得分:0)
对于那些在迭代之间没有依赖关系的情况,broadcasting
似乎是将对角1D数组的维度扩展为具有None/np.newaxis
的2D版本并使用其1D版本执行计算后的明显方法分别模拟A[i,i]
和A[j,j]
。因此,要解决这两种情况,可以这样做 -
Ad = np.diag(A)
case1_out_vectorized = 1/(Ad[:,None] + Ad - 2*A)
case2_out_vectorized = A/np.sqrt(Ad[:,None]*Ad)
示例运行 -
In [33]: # Random input array
...: A = np.random.rand(4,4)
...:
...: # Naive loopy implmentation (used here for verification)
...: m = A.shape[0]
...: case1_out_loopy = np.zeros((m,m))
...: case2_out_loopy = np.zeros((m,m))
...: for i in range(m):
...: for j in range(m):
...: case1_out_loopy[i,j] = 1/(A[i,i] + A[j,j] - 2*A[i,j])
...: case2_out_loopy[i,j] = A[i,j]/np.sqrt(A[i,i]*A[j,j])
...:
In [34]: # Proposed approach
...: Ad = np.diag(A)
...: case1_out_vectorized = 1/(Ad[:,None] + Ad - 2*A)
...: case2_out_vectorized = A/np.sqrt(Ad[:,None]*Ad)
...:
In [35]: np.allclose(case1_out_loopy,case1_out_vectorized)
Out[35]: True
In [36]: np.allclose(case2_out_loopy,case2_out_vectorized)
Out[36]: True