【问题标题】:Making a numpy ndarray matrix symmetric使 numpy ndarray 矩阵对称
【发布时间】:2015-05-08 09:21:44
【问题描述】:

我有一个 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

【问题讨论】:

标签: python matlab numpy matrix


【解决方案1】:

找到以下适合我的解决方案:

import numpy as np
W = np.maximum( A, A.transpose() )

【讨论】:

  • 问题是如果你的矩阵A很大,那么这会浪费很多空间,因为我想它会创建第二个矩阵,或者不是吗?
  • 如果您尝试镜像的非对角线元素是负数,这将不起作用,不是吗?
  • 在处理负系数时,您只需执行W = (A + A.transpose()) / 2
【解决方案2】:

如下使用 NumPy triltriu 函数。它本质上是将下三角形中的元素“镜像”到上三角形中。

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 的副本,其中kth 对角线上方的所有元素都归零)。同样,triu(m, k=0) 获取矩阵 m 的上三角形(kth 对角线下方的所有元素都归零)。

为防止对角线被添加两次,必须使用np.tril(A) + np.triu(A.T, 1)np.tril(A, -1) + np.triu(A.T) 从其中一个三角形中排除对角线。

另请注意,这与使用 maximum 的行为略有不同。上三角形中的所有元素都被覆盖,无论它们是否为最大值。这意味着它们可以是任何值(例如 naninf)。

【讨论】:

    【解决方案3】:

    就其价值而言,使用您提到的 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
    

    【讨论】:

    • 大约是 3 倍。它是否适用于更大的矩阵,比如 100x100 或 1000x1000?
    • @xeon 我为你提到的尺寸添加了时间。这些时间在我的机器 YMMV 上。 ~2x 的差异来自执行的操作数量。两者都使用 numpy 对象和 numpy 方法。与 MATLAB 类似,numpy 旨在优化矩阵运算,因此 numpy 方法通常是最有效的。
    • 我将 A.transpose() 换成 A.T 以指出它们是相同的,并且需要更少的输入 (docs.scipy.org/doc/numpy/reference/generated/…)。
    猜你喜欢
    • 2011-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-04
    • 2016-05-09
    相关资源
    最近更新 更多