对于3D数组

时间:2017-02-10 11:23:41

标签: python arrays r numpy matrix

我正在将一些代码从Python翻译成涉及3D矩阵的R.这很棘手,因为我对Python或矩阵代数知之甚少。无论如何在Python代码中我有一个矩阵dot.product如下:np.dot(A, B)。矩阵A具有尺寸(10,4),B是(2,4,2)。 (这些尺寸可能会有所不同,但总是会在第二个尺寸上匹配)。所以np.dot对文档没有任何问题:

  

"对于2-D阵列,它相当于矩阵乘法,对于1-D   阵列到载体的内积(没有复共轭)。对于   N维是a和a的最后一个轴上的和积   b的倒数第二个:"

因此它沿着A = 4的第二轴和B = 4的中轴相乘并输出(10,2,2)矩阵。 =>没问题。但是在R中,%*%没有这种行为并抛出一个不合适的数组'错误。

r中的玩具示例:

A <- matrix( rnorm(10*4), nrow=10, ncol=4)
B <- array( rnorm(2*4*2), c(2,4,2))
A %*% B
Error in A %*% B : non-conformable arrays

如何解决此问题以实现与np.dot相同的计算?

2 个答案:

答案 0 :(得分:4)

我们可以使用aperm()tensor::tensor执行此操作。使用@ SandipanDey的例子。

设置数组(你需要aperm来获得适当的B,我在这里称之为B2):

A <- matrix(0:39,ncol=4,byrow=TRUE)
B <- array(0:15,dim=c(2,4,2))
B2 <- aperm(B,c(2,1,3),resize=TRUE)

tensor::tensor做正确的计算,但我们需要重塑结果:

library(tensor)
C <- tensor(A,B2,2,1)
aperm(C,c(3,2,1),resize=TRUE)

答案 1 :(得分:3)

让我们首先尝试理解在python numpyR中填充多维数组的顺序,它们是不同的。

python

import numpy as np
np.arange(16).reshape((2,4,2)) # fill with 0:15

#[[[ 0  1]
#  [ 2  3]
#  [ 4  5]
#  [ 6  7]]

# [[ 8  9]
#  [10 11]
#  [12 13]
#  [14 15]]]

R

array(0:15, dim=c(2,4,2)) # fill with 0:15
#, , 1
#      [,1] [,2] [,3] [,4]
#[1,]    0    2    4    6
#[2,]    1    3    5    7
#, , 2
#     [,1] [,2] [,3] [,4]
#[1,]    8   10   12   14
#[2,]    9   11   13   15

现在了解填充顺序,让我们尝试使用相同的数据模拟R中的np.dotA,B作为输入数组,C作为输出数组(为此我们需要改变维度的顺序):

python

import numpy as np
a = np.arange(40).reshape((10,4))    # 0:39
b = np.arange(16).reshape((2,4,2))   # 0:15

print a
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]
 [16 17 18 19]
 [20 21 22 23]
 [24 25 26 27]
 [28 29 30 31]
 [32 33 34 35]
 [36 37 38 39]]

print b
[[[ 0  1]
  [ 2  3]
  [ 4  5]
  [ 6  7]]

 [[ 8  9]
  [10 11]
  [12 13]
  [14 15]]]

print np.dot(a, b)
[[[  28   34]
  [  76   82]]

 [[  76   98]
  [ 252  274]]

 [[ 124  162]
  [ 428  466]]

 [[ 172  226]
  [ 604  658]]

 [[ 220  290]
  [ 780  850]]

 [[ 268  354]
  [ 956 1042]]

 [[ 316  418]
  [1132 1234]]

 [[ 364  482]
  [1308 1426]]

 [[ 412  546]
  [1484 1618]]

 [[ 460  610]
  [1660 1810]]]

R中获得相同的结果,我们需要以下代码:

A <- matrix(0:39, nrow=10, byrow=TRUE) # 0:39
A
      [,1] [,2] [,3] [,4]
 [1,]    0    1    2    3
 [2,]    4    5    6    7
 [3,]    8    9   10   11
 [4,]   12   13   14   15
 [5,]   16   17   18   19
 [6,]   20   21   22   23
 [7,]   24   25   26   27
 [8,]   28   29   30   31
 [9,]   32   33   34   35
[10,]   36   37   38   39

B <- array(0, dim=c(4,2,2)) # notice the change in dimensions
B[,,1] <- matrix(0:7, nrow=4, byrow=TRUE)
B[,,2] <- matrix(8:15, nrow=4, byrow=TRUE)
B                                 # 0:15
, , 1

     [,1] [,2]
[1,]    0    1
[2,]    2    3
[3,]    4    5
[4,]    6    7

, , 2

     [,1] [,2]
[1,]    8    9
[2,]   10   11
[3,]   12   13
[4,]   14   15

C <- array(0, dim=c(2,2,10)) # again note the change in dimensions
for (i in 1:10) {
  for (j in 1:2) {
    for (k in 1:2) {
      C[k,j,i] = sum(A[i,]*B[,j,k])
    }
  }
}
C
, , 1

     [,1] [,2]
[1,]   28   34
[2,]   76   82

, , 2

     [,1] [,2]
[1,]   76   98
[2,]  252  274

, , 3

     [,1] [,2]
[1,]  124  162
[2,]  428  466

, , 4

     [,1] [,2]
[1,]  172  226
[2,]  604  658

, , 5

     [,1] [,2]
[1,]  220  290
[2,]  780  850

, , 6

     [,1] [,2]
[1,]  268  354
[2,]  956 1042

, , 7

     [,1] [,2]
[1,]  316  418
[2,] 1132 1234

, , 8

     [,1] [,2]
[1,]  364  482
[2,] 1308 1426

, , 9

     [,1] [,2]
[1,]  412  546
[2,] 1484 1618

, , 10

     [,1] [,2]
[1,]  460  610
[2,] 1660 1810  

我们可以看到结果完全相同。现在,您可以尝试使用自己的数据。