【问题标题】:How to convert triangle matrix to square in NumPy?如何在 NumPy 中将三角形矩阵转换为正方形?
【发布时间】:2016-07-15 00:38:46
【问题描述】:

我正在对冗余的完整矩阵进行一些计算(即可以是三角形矩阵而不会丢失信息)。我意识到我只能计算三角形的下部以获得更快的结果。完成后如何将下三角投影到上三角?

也就是说,我该如何反转np.tril方法?

print DF_var.as_matrix()
# [[1 1 0 1 1 1 0 1 0 0 0]
#  [1 1 1 1 1 0 1 0 1 1 1]
#  [0 1 1 0 0 0 0 0 0 0 0]
#  [1 1 0 1 0 0 0 0 0 0 0]
#  [1 1 0 0 1 0 0 0 0 0 0]
#  [1 0 0 0 0 1 1 0 0 0 0]
#  [0 1 0 0 0 1 1 0 0 0 0]
#  [1 0 0 0 0 0 0 1 1 0 0]
#  [0 1 0 0 0 0 0 1 1 0 0]
#  [0 1 0 0 0 0 0 0 0 1 0]
#  [0 1 0 0 0 0 0 0 0 0 1]]
print np.tril(DF_var.as_matrix())
# [[1 0 0 0 0 0 0 0 0 0 0]
#  [1 1 0 0 0 0 0 0 0 0 0]
#  [0 1 1 0 0 0 0 0 0 0 0]
#  [1 1 0 1 0 0 0 0 0 0 0]
#  [1 1 0 0 1 0 0 0 0 0 0]
#  [1 0 0 0 0 1 0 0 0 0 0]
#  [0 1 0 0 0 1 1 0 0 0 0]
#  [1 0 0 0 0 0 0 1 0 0 0]
#  [0 1 0 0 0 0 0 1 1 0 0]
#  [0 1 0 0 0 0 0 0 0 1 0]
#  [0 1 0 0 0 0 0 0 0 0 1]]

如何将其转换回完整的矩阵?

【问题讨论】:

    标签: python arrays numpy matrix linear-algebra


    【解决方案1】:

    由于矩阵是对称的,你可以这样做:

    m = np.array([1,1,0,1,1,1,0,1,1]).reshape((3,3))
    
    # after some computation you get x
    x = np.tril(m)
    
    m_recomposed = x + x.transpose() - np.diag(np.diag(x))
    
    #array([[1, 1, 0],
    #       [1, 1, 1],
    #       [0, 1, 1]])
    
    #In [152]: np.array_equal(m, m_recomposed)
    #Out[152]: True
    

    【讨论】:

      【解决方案2】:

      假设A作为输入数组,下面列出几个方法。

      方法#1:A的转置版本上使用np.triu -

      np.triu(A.T,1) + A
      

      方法 #2: 避免 np.triu 在 A.T 和 A 之间直接求和,然后通过索引设置对角线元素 -

      out = A.T + A
      idx = np.arange(A.shape[0])
      out[idx,idx] = A[idx,idx]
      

      方法 #3: 与前一种方法相同,但使用内置索引进行紧凑 -

      out = A.T + A
      np.fill_diagonal(out,np.diag(A))
      

      方法 #4: 与上一个相同,但使用布尔索引来设置对角线元素 -

      out = A.T + A
      mask = np.eye(out.shape[0],dtype=bool)
      out[mask] = A[mask]
      

      方法 #5: 使用基于掩码的对角元素选择 np.where -

      np.where(np.eye(A.shape[0],dtype=bool),A,A.T+A)
      

      方法 #6: 使用 np.where 对所有元素使用基于掩码的选择 -

      np.where(np.triu(np.ones(A.shape[0],dtype=bool),1),A.T,A)
      

      运行时测试

      函数-

      def func1(A):
          return np.triu(A.T,1) + A
      
      def func2(A):
          out = A.T + A
          idx = np.arange(A.shape[0])
          out[idx,idx] = A[idx,idx]
          return out
      
      def func3(A):
          out = A.T + A
          np.fill_diagonal(out,np.diag(A))
          return out
      
      def func4(A):
          out = A.T + A
          mask = np.eye(out.shape[0],dtype=bool)
          out[mask] = A[mask]
          return out
      
      def func5(A):
          return np.where(np.eye(A.shape[0],dtype=bool),A,A.T+A)
      
      def func6(A):
          return np.where(np.triu(np.ones(A.shape[0],dtype=bool),1),A.T,A)
      

      时间安排 -

      In [140]: # Input array
           ...: N = 5000
           ...: A = np.tril(np.random.randint(0,9,(N,N)))
           ...: 
      
      In [141]: %timeit func1(A)
           ...: %timeit func2(A)
           ...: %timeit func3(A)
           ...: %timeit func4(A)
           ...: %timeit func5(A)
           ...: %timeit func6(A)
           ...: 
      1 loops, best of 3: 617 ms per loop
      1 loops, best of 3: 354 ms per loop
      1 loops, best of 3: 354 ms per loop
      1 loops, best of 3: 395 ms per loop
      1 loops, best of 3: 597 ms per loop
      1 loops, best of 3: 440 ms per loop
      

      看起来方法 #2 和 #3 非常有效!

      【讨论】:

      • 哇@divakar,这是一个令人难以置信和全面的答案。看到所有这些解决这个问题的方法真的很有帮助。我肯定会一遍又一遍地提到这个。
      • 和表演对比真的很不错,谢谢解答!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-03-29
      • 1970-01-01
      • 1970-01-01
      • 2013-05-02
      • 1970-01-01
      • 1970-01-01
      • 2022-11-29
      相关资源
      最近更新 更多