2017-02-10 93 views
2

的我正在翻譯在Python至R一些代碼涉及3D矩陣。這是非常棘手的,因爲我知道很少的Python或矩陣代數。總之在Python代碼中,我有一個矩陣dot.product如下:np.dot(A, B)。矩陣A有尺寸(10,4),B是(2,4,2)。 (這些尺寸可能會有所不同,但始終會在第二維上匹配)。所以np.dot與此沒有問題作爲從文檔:- [R等效Python的np.dot爲3D陣列

「對於2-d陣列它相當於矩陣乘法,以及用於1-d 陣列矢量的內積(無複共軛)對於 N維它結束的最後一個軸和一個和積的 第二到最後一個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

+1

'B'是一個二維數組,對於一個三維數組,你需要函數'array()'。你也使用'%%'而不是'%*%'。 – LyzandeR

+0

感謝是我應該用'陣列()'和'%*%'。有錯別字!現在解決。無論如何 - 修復後的結果是一樣的 – user2498193

回答

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) 
+0

非常感謝你這正是我正在尋找。不知道'張量'包,我將不得不熟悉自己! – user2498193

2

我們先來試着瞭解在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 

現在具有的填充順序的瞭解,讓我們試圖模仿np.dot中的R具有相同的數據,A,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 

我們可以看到的結果是完全一樣的。現在您可以嘗試使用自己的數據。

+0

謝謝你的回答,但是對我來說沒有什麼意義,比如'#注意到尺寸的變化。你已經定義了一個(4,2,2)矩陣,但是我的是一個(2,4,2)矩陣,來自另一個函數的結果。 – user2498193

+1

如果您沒有訪問該函數,那麼您可以編寫一個小型轉換函數,根據需要將陣列輸出更改爲所需的格式。所有我想要溝通的是,如果你自己創建一個數組,那麼維度的順序需要與numpy不同。如果返回數組的函數以正確的格式返回它,那麼我們應該沒問題。 –

+0

好的我非常感謝你! – user2498193