Re: [問題] 兩個矩陣同時操作

作者: celestialgod (天)   2017-07-13 21:36:54
這種事情殺雞焉用牛刀,用迴圈最快也最簡單
A <- matrix(c(1:48),ncol = 16L)
B <- matrix(c(1:80),ncol = 16L)
mutual <- function(delta, a, FUN = "*"){
delta <- as.matrix(delta)
a <- as.matrix(a)
result <- matrix(outer(delta, a, FUN), nrow = nrow(delta))
return(result)
}
f <- function(a,b){
return(as.matrix(a) %*% t(b))
}
g <- function(A, B){
out <- array(dim = c(nrow(A), nrow(B), ncol(A)))
for (i in 1L:ncol(A)) out[ , , i] <- A[ , i] %o% B[ , i]
return(out)
}
library(microbenchmark)
microbenchmark(
original = lapply(1L:ncol(A) , function(x) mutual(A[,x], B[,x])),
simplify2array = simplify2array(lapply(1:ncol(A) , function(x) f(A[,x],
B[,x]))),
forLoop = g(A, B), times = 20L
)
# Unit: microseconds
# expr min lq mean median uq max neval
# original 419.838 423.6410 702.6495 426.2735 431.6865 5669.115 20
# simplify2array 222.938 224.8400 389.2933 229.0820 236.2500 3406.385 20
# forLoop 183.734 187.5375 486.0899 190.7555 195.4375 5987.723 20
不過我的R是3.4.0,所以JIT加持快很多,不確定其他版本是不是一樣水準
A <- matrix(c(1:48000), ncol = 1600L)
B <- matrix(c(1:8000), ncol = 1600L)
microbenchmark(
original = lapply(1L:ncol(A) , function(x) mutual(A[,x], B[,x])),
simplify2array = simplify2array(lapply(1:ncol(A) , function(x) f(A[,x],
B[,x]))),
forLoop = g(A, B), times = 20L
)
# Unit: milliseconds
# expr min lq mean median uq max neval
# original 44.37369 46.77744 48.24738 47.98765 49.32776 53.08230 20
# simplify2array 21.89062 23.83928 28.64161 25.65306 26.21406 94.59203 20
# forLoop 21.23322 22.69387 24.72092 24.64764 25.65935 31.67589 20
※ 引述《wheado (principal component QQ)》之銘言:
: [問題類型]:
: 兩個滿大的矩陣同時透過row來進行操作
: 用一個例子來說明我的問題
: [軟體熟悉度]:
: 新手
: [問題敘述]:
: A=[ 1 2 3 4 ] B=[ 1 2 3 4 ] A與B的column相同
: [ 5 6 7 8 ] [ 5 6 7 8 ]
: [ 9 10 11 12 ] [ 9 10 11 12 ]
: [ 13 14 15 16 ] [ 13 14 15 16 ]
: [ 17 18 19 20 ] [ 17 18 19 20 ]
: [ 21 22 23 24 ]
: [ 25 26 27 28 ]
: [ 29 30 31 32 ]
: 我想透過類似apply的運算,將A與B兩個矩陣的Column分別提出來運算,
: 運算內容是有點複雜,用上述例子來說明。
: A* B*
: 以第一個column來說,提出來的分別是 [ 1 ] [ 1 ]
: [ 5 ] [ 5 ]
: [ 9 ] [ 9 ]
: [ 13 ] [ 13 ]
: [ 17 ] [ 17 ]
: [ 21 ]
: [ 25 ]
: [ 29 ]
: 接著將A*每個元素與B*每個元素"乘積",也就是產生一個矩陣(向量也可以)如下
: [ 1*1 1*5 1*9 1*13 1*17 1*21 1*25 1*29 ]
: [ 5*1 5*5 5*9 5*13 5*17 5*21 5*25 5*29 ]
: [ 9*1 9*5 9*9 9*13 9*17 9*21 9*25 9*29 ]
: [ 13*1 13*5 13*9 13*13 13*17 13*21 13*25 13*29 ]
: [ 17*1 17*5 17*9 17*13 17*17 17*21 17*25 17*29 ]
: 以此類推會產生 4 個矩陣(或向量),輸出方式目前想到只有 list 比較方便。
: 由於我們兩個矩陣A與B可能會有點大,因此希望可以稍微快一些的計算方法,
: 又希望程式碼可讀性可以高一點,讓自己以後比較容易看懂(修改)。
: ~~~謝謝各位神人閱讀~~~
: [程式範例]:
: 我有嘗試了一個方式,但我覺得可讀性很低,
: 希望可以改的更簡單易懂,速度更快一些。
: 我是用 指令outer 來做,以下程式碼,矩陣大一點就要等一些時間了QQ
: 程式碼貼於以下網址:
: http://ideone.com/NmFGVT
: [環境敘述]:
: win10 + R_64
: [關鍵字]:
: outer apply mapply lapply
作者: wheado (principal component QQ)   2017-07-13 21:49:00
謝謝大師不厭其煩指教,直覺上就是想避開loop,沒想到loop威力還真是簡單強大。
作者: f496328mm (為什麼會流淚)   2017-07-13 21:53:00
R 3.4 有加強迴圈的威力
作者: Edster (Edster)   2017-07-13 22:02:00
for迴圈變快真是好消息.
作者: sacidoO (阿罵)   2017-07-15 22:35:00
推C神

Links booklink

Contact Us: admin [ a t ] ucptt.com