我有一个 70x70 numpy ndarray,主要是对角线。唯一的非对角线值是对角线下方的值。我想让矩阵对称。
作为 Matlab 世界的新手,如果没有 for 循环,我就无法让它工作。在 MATLAB 中这很简单:
W = max(A,A')
其中
A'
是矩阵转置,max()
函数负责使 W 矩阵成为对称的。
Python 中也有一种优雅的方法吗?
示例 样本
A
矩阵为:
1 0 0 0
0 2 0 0
1 0 2 0
0 1 0 3
期望的输出矩阵
W
是:
1 0 1 0
0 2 0 1
1 0 2 0
0 1 0 3
找到了以下适合我的解决方案:
import numpy as np
W = np.maximum( A, A.transpose() )
tril
和 triu
函数,如下所示。它本质上是将下三角形中的元素“镜像”到上三角形中。
import numpy as np
A = np.array([[1, 0, 0, 0], [0, 2, 0, 0], [1, 0, 2, 0], [0, 1, 0, 3]])
W = np.tril(A) + np.triu(A.T, 1)
tril(m, k=0)
获取矩阵 m
的下三角形(返回矩阵 m
的副本,其中第 k
对角线上方的所有元素均为零)。类似地, triu(m, k=0)
获取矩阵 m
的上三角形(第 k
对角线下方的所有元素都归零)。
为了防止对角线添加两次,必须使用
np.tril(A) + np.triu(A.T, 1)
或 np.tril(A, -1) + np.triu(A.T)
从其中一个三角形中排除对角线。
另请注意,这与使用
maximum
的行为略有不同。上三角形中的所有元素都会被覆盖,无论它们是否是最大值。这意味着它们可以是任何值(例如 nan
或 inf
)。
就其价值而言,使用您提到的 MATLAB 的 numpy 等效项比添加的 link @plonser 更有效。
In [1]: import numpy as np
In [2]: A = np.zeros((4, 4))
In [3]: np.fill_diagonal(A, np.arange(4)+1)
In [4]: A[2:,:2] = np.eye(2)
# numpy equivalent to MATLAB:
In [5]: %timeit W = np.maximum( A, A.T)
100000 loops, best of 3: 2.95 µs per loop
# method from link
In [6]: %timeit W = A + A.T - np.diag(A.diagonal())
100000 loops, best of 3: 9.88 µs per loop
较大矩阵的计时可以类似地完成:
In [1]: import numpy as np
In [2]: N = 100
In [3]: A = np.zeros((N, N))
In [4]: A[2:,:N-2] = np.eye(N-2)
In [5]: np.fill_diagonal(A, np.arange(N)+1)
In [6]: print A
Out[6]:
array([[ 1., 0., 0., ..., 0., 0., 0.],
[ 0., 2., 0., ..., 0., 0., 0.],
[ 1., 0., 3., ..., 0., 0., 0.],
...,
[ 0., 0., 0., ..., 98., 0., 0.],
[ 0., 0., 0., ..., 0., 99., 0.],
[ 0., 0., 0., ..., 1., 0., 100.]])
# numpy equivalent to MATLAB:
In [6]: %timeit W = np.maximum( A, A.T)
10000 loops, best of 3: 28.6 µs per loop
# method from link
In [7]: %timeit W = A + A.T - np.diag(A.diagonal())
10000 loops, best of 3: 49.8 µs per loop
N = 1000
# numpy equivalent to MATLAB:
In [6]: %timeit W = np.maximum( A, A.T)
100 loops, best of 3: 5.65 ms per loop
# method from link
In [7]: %timeit W = A + A.T - np.diag(A.diagonal())
100 loops, best of 3: 11.7 ms per loop
可以得到对称正定
import pandas as pd
from sklearn.datasets import make_spd_matrix # spd - symmetric positive-definite matrix
spd = make_spd_matrix(n_dim=3, random_state=1)
print(pd.DataFrame(spd))