numpy矩阵算法及其对角元素

时间:2016-04-19 05:35:28

标签: python numpy

我喜欢numpy因为它允许矢量化操作,例如:

mat1 = np.array([[1,2],[3,4]])
mat2 = np.array([[10,20],[30,40]])
mat3 = (mat1 + mat2)*2.0 # vectorization way. nice.

但是,我找不到如何用对角线元素进行这种操作。我想做的是

B_{ij}=1/(A_{i,i}+A_{j,j}-2*A_{i,j})

B_{ij}=A_{i,j}/\sqrt{A_{i,i}*A_{j,j}}

是否可以使用numpy以矢量化方式在上面进行操作?

2 个答案:

答案 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