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

看板R_Language作者 (天)時間8年前 (2017/07/13 21:36), 8年前編輯推噓3(302)
留言5則, 4人參與, 最新討論串2/2 (看更多)
這種事情殺雞焉用牛刀,用迴圈最快也最簡單 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 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 36.232.188.7 ※ 文章網址: https://www.ptt.cc/bbs/R_Language/M.1499953018.A.279.html ※ 編輯: celestialgod (36.232.188.7), 07/13/2017 21:37:17 ※ 編輯: celestialgod (36.232.188.7), 07/13/2017 21:42:29

07/13 21:49, , 1F
謝謝大師不厭其煩指教,直覺上就是想避開loop,沒想到loop
07/13 21:49, 1F

07/13 21:49, , 2F
威力還真是簡單強大。
07/13 21:49, 2F

07/13 21:53, , 3F
R 3.4 有加強迴圈的威力
07/13 21:53, 3F

07/13 22:02, , 4F
for迴圈變快真是好消息.
07/13 22:02, 4F
其實R迴圈改array很快... ※ 編輯: celestialgod (36.232.188.7), 07/13/2017 22:06:09

07/15 22:35, , 5F
推C神
07/15 22:35, 5F
文章代碼(AID): #1PPtTw9v (R_Language)
討論串 (同標題文章)
文章代碼(AID): #1PPtTw9v (R_Language)