【问题标题】:Matrix Multiplication in Numpy (Converting 2d to 3d)Numpy 中的矩阵乘法(将 2d 转换为 3d)
【发布时间】:2018-06-05 22:31:09
【问题描述】:

我有一个矩阵:

[
 [ 5 10 15 20]
 [ 6 12 18 24]
 [ 7 14 21 28]
 [ 8 16 24 32]
]

即 (4x4)。

我想制作一个 (4x4x4) 矩阵,如下所示:

[
 [
  [ 5 0 0 0]
  [ 6 0 0 0]
  [ 7 0 0 0]
  [ 8 0 0 0]]
 [
  [ 0 10 0 0]
  [ 0 12 0 0]
  [ 0 14 0 0]
  [ 0 16 0 0]]
 [
  [ 0 0 15 0]
  [ 0 0 18 0]
  [ 0 0 21 0]
  [ 0 0 24 0]]
 [
  [ 0 0 0 20]
  [ 0 0 0 24]
  [ 0 0 0 28]
  [ 0 0 0 32]]
]

以矩阵方式执行此操作的最佳方法是什么(不使用 for 循环)?

【问题讨论】:

    标签: python numpy matrix


    【解决方案1】:

    你可以通过将它乘以一个带有额外轴的对角数组来做到这一点:

    >>> a = np.arange(16).reshape(4,4)
    >>> a
    array([[ 0,  1,  2,  3],
           [ 4,  5,  6,  7],
           [ 8,  9, 10, 11],
           [12, 13, 14, 15]])
    >>> a*np.eye(4)[:,np.newaxis]
    array([[[  0.,   0.,   0.,   0.],
            [  4.,   0.,   0.,   0.],
            [  8.,   0.,   0.,   0.],
            [ 12.,   0.,   0.,   0.]],
    
           [[  0.,   1.,   0.,   0.],
            [  0.,   5.,   0.,   0.],
            [  0.,   9.,   0.,   0.],
            [  0.,  13.,   0.,   0.]],
    
           [[  0.,   0.,   2.,   0.],
            [  0.,   0.,   6.,   0.],
            [  0.,   0.,  10.,   0.],
            [  0.,   0.,  14.,   0.]],
    
           [[  0.,   0.,   0.,   3.],
            [  0.,   0.,   0.,   7.],
            [  0.,   0.,   0.,  11.],
            [  0.,   0.,   0.,  15.]]])
    

    【讨论】:

      【解决方案2】:

      您可以创建一个具有所需形状的零数组,然后使用简单的索引来用数组的列填充预期的索引:

      x, y = a.shape
      arr = np.zeros((x, y, y))
      ind = np.arange(y)
      arr[ind,:,ind] = a.T
      

      演示:

      In [40]: a = np.array([
          ...:  [ 5 ,10 ,15, 20],
          ...:  [ 6, 12, 18, 24],
          ...:  [ 7, 14, 21, 28],
          ...:  [ 8, 16, 24, 32]
          ...: ])
      
      In [43]: arr[np.arange(4),:,np.arange(4)] = a.T
      
      In [44]: arr
      Out[44]: 
      array([[[ 5.,  0.,  0.,  0.],
              [ 6.,  0.,  0.,  0.],
              [ 7.,  0.,  0.,  0.],
              [ 8.,  0.,  0.,  0.]],
      
             [[ 0., 10.,  0.,  0.],
              [ 0., 12.,  0.,  0.],
              [ 0., 14.,  0.,  0.],
              [ 0., 16.,  0.,  0.]],
      
             [[ 0.,  0., 15.,  0.],
              [ 0.,  0., 18.,  0.],
              [ 0.,  0., 21.,  0.],
              [ 0.,  0., 24.,  0.]],
      
             [[ 0.,  0.,  0., 20.],
              [ 0.,  0.,  0., 24.],
              [ 0.,  0.,  0., 28.],
              [ 0.,  0.,  0., 32.]]])
      

      使用np.eye()、乘法和广播的其他答案的基准测试表明,这个答案的速度是原来的两倍。

      In [46]: def use_zeros(arr):
          ...:     x, y = arr.shape
          ...:     z = np.zeros((x, y, y))
          ...:     ind = np.arange(y)
          ...:     z[ind,:,ind] = a.T
          ...:     return z
          ...: 
          ...: 
      
      In [47]: def use_eye(arr):
          ...:     return arr*np.eye(arr.shape[1])[:,np.newaxis]
          ...: 
          ...: 
      
      In [48]: a = np.arange(10000).reshape(100,100)
      
      In [49]: %timeit use_zeros(a)
      1.23 ms ± 14.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
      
      In [50]: %timeit use_eye(a)
      2.47 ms ± 23.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
      

      【讨论】:

      • .. 我想知道为什么这个答案被否决了?对我来说看起来很棒。
      • @miradulo 如果背后有合理的原因,您会在这里看到它作为评论:)。使用基准检查更新。
      • 是的,eye 解决方案也不错,但像这样就地设置更快,内存效率更高。
      猜你喜欢
      • 1970-01-01
      • 2016-08-25
      • 2016-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-30
      • 2015-12-08
      相关资源
      最近更新 更多