Skip to content

efficiently multiply different matrices in 3-d array with different vectors?

7 messages · Ranjan Maitra, Suzen, Mehmet, arun

#
Hello,

I have been wondering of an efficient way to do this:

I have an n x m x p array Z and a p x n matrix Y.

I want to multiply each of the n matrices with the corresponding column
vector of Y.

In other words, I am wanting to matrix multiply: 

Z[i, ,] %*% Y[, i]

which will give me a (two-dimensional) array or matrix of dimension n x
p with the i'th row storing the above.

Any pointers on an efficient way of doing this? I considered using
apply, but was not successful. 

Many thanks again and best wishes,
Ranjan
#
I think what you are doing is a tensor algebra. You may want to try tensorA:

http://cran.r-project.org/web/packages/tensorA/index.html
On 28 December 2012 06:33, Ranjan Maitra <maitra.mbox.ignored at inbox.com> wrote:
please post that code. Why it was not successful? What was the error message?
#
HI,

Not sure if this is what you wanted:
set.seed(14)
Z<-array(sample(1:100,80,replace=TRUE),dim=c(5,2,8))
set.seed(21)
Y<-matrix(sample(1:40,40,replace=TRUE),nrow=8)
do.call(cbind,lapply(seq_len(dim(Z)[1]),function(i) Z[i,,]%*%Y[,i]))
#???? [,1] [,2]? [,3]? [,4]? [,5]
#[1,] 5065 6070 12328 11536 13678
#[2,] 6152 9878 11161 13777? 7991
A.K.




----- Original Message -----
From: Ranjan Maitra <maitra.mbox.ignored at inbox.com>
To: r-help at r-project.org
Cc: 
Sent: Friday, December 28, 2012 12:33 AM
Subject: [R] efficiently multiply different matrices in 3-d array with different vectors?

Hello,

I have been wondering of an efficient way to do this:

I have an n x m x p array Z and a p x n matrix Y.

I want to multiply each of the n matrices with the corresponding column
vector of Y.

In other words, I am wanting to matrix multiply: 

Z[i, ,] %*% Y[, i]

which will give me a (two-dimensional) array or matrix of dimension n x
p with the i'th row storing the above.

Any pointers on an efficient way of doing this? I considered using
apply, but was not successful. 

Many thanks again and best wishes,
Ranjan
#
On Thu, 27 Dec 2012 22:03:19 -0800 arun <smartpink111 at yahoo.com> wrote:

            
Yes, this does it, many thanks!

Ranjan

  
    
1 day later
#
What I had in mind was a tensor multiplication.
I think,  using tensor arithmetic for multidimensional arrays looks
more compacts
and efficient (~ 2-3 times). I am guessing that performance will be much more
pronounced for n-D arrays (n>3).

# Component Wise
set.seed(14)
Z<-array(sample(1:1000000,800000,replace=TRUE),dim=c(50000,2,8))
set.seed(21)
Y<-matrix(sample(1:400000,400000,replace=TRUE),nrow=8)
system.time(X<-do.call(cbind,lapply(seq_len(dim(Z)[1]),function(i)
Z[i,,]%*%Y[,i])))
#   user  system elapsed
#   0.58    0.00    0.58
R<-cbind(sum(X[1,]), sum(X[2,]))
# Tensor multiply
library(tensorA)
set.seed(14)
Zt <-to.tensor(sample(1:1000000,800000,replace=TRUE), c(a=50000, b=2, c=8))
set.seed(21)
Yt <-to.tensor(sample(1:400000,400000,replace=TRUE), c(c=8, a=50000))
system.time(Rt<-Zt %e% Yt)
#   user  system elapsed
#  0.124   0.000   0.126
# correct results?
R
#            [,1]         [,2]
#[1,] 4.00595e+16 3.997387e+16
Rt
#[1] 4.005950e+16 3.997387e+1
#
HI,
Tx for the fast method.
dim(Rt)
#b 
#2 
?dim(X)
#[1]???? 2 50000


Is it possible to obtain the same result as X without converting X to R??? 

According to OP "..... which will give me a (two-dimensional) array or matrix of dimension n x 
p with the i'th row storing the above.
"

A.K.





----- Original Message -----
From: "Suzen, Mehmet" <msuzen at gmail.com>
To: arun <smartpink111 at yahoo.com>
Cc: Ranjan Maitra <maitra.mbox.ignored at inbox.com>; R help <r-help at r-project.org>
Sent: Saturday, December 29, 2012 1:19 PM
Subject: Re: [R] efficiently multiply different matrices in 3-d array with different vectors?

What I had in mind was a tensor multiplication.
I think,? using tensor arithmetic for multidimensional arrays looks
more compacts
and efficient (~ 2-3 times). I am guessing that performance will be much more
pronounced for n-D arrays (n>3).

# Component Wise
set.seed(14)
Z<-array(sample(1:1000000,800000,replace=TRUE),dim=c(50000,2,8))
set.seed(21)
Y<-matrix(sample(1:400000,400000,replace=TRUE),nrow=8)
system.time(X<-do.call(cbind,lapply(seq_len(dim(Z)[1]),function(i)
Z[i,,]%*%Y[,i])))
#?  user? system elapsed
#?  0.58? ? 0.00? ? 0.58
R<-cbind(sum(X[1,]), sum(X[2,]))
# Tensor multiply
library(tensorA)
set.seed(14)
Zt <-to.tensor(sample(1:1000000,800000,replace=TRUE), c(a=50000, b=2, c=8))
set.seed(21)
Yt <-to.tensor(sample(1:400000,400000,replace=TRUE), c(c=8, a=50000))
system.time(Rt<-Zt %e% Yt)
#?  user? system elapsed
#? 0.124?  0.000?  0.126
# correct results?
R
#? ? ? ? ? ? [,1]? ? ? ?  [,2]
#[1,] 4.00595e+16 3.997387e+16
Rt
#[1] 4.005950e+16 3.997387e+1
#
On 29 December 2012 20:35, arun <smartpink111 at yahoo.com> wrote:
What do you mean by the same result? There is a relationship between X and R.
If you express this relationship algebraically, you can get X directly using
Y and Z tensors, vice versa.

Too many terms in the example you have given. So I would demonstrate
the possibility
with a smaller example. Think of X as intermediate results from Matrix
multiplication.
You need to use Riemann notation instead of Einstein's [*]. However
you may end up computing more terms then you need.

It makes sense to use tensorA only if you know algebraic relationships
well. If you think
in terms of components and positioning intermediate results as most R
programmers do
 i,e. using cbind, moving that column here in there etc,,  probably
tensorA is not suited
for you.

Hope it answers your question.

[*]
library(tensorA)
# intermediate results via component wise multiplication
set.seed(42)
A <-matrix(rnorm(10), 5, 2)
set.seed(43)
x <-matrix(rnorm(2), 2, 1)
b <- A %*% x
bInter <- do.call(cbind,lapply(seq_len(dim(A)[1]),function(i) A[i,]*x))
# intermediate results via tensor multiplication
set.seed(42)
At <-to.tensor(rnorm(10), c(a=5, b=2))
set.seed(43)
xt <-to.tensor(rnorm(2), c(c=2))
bt <- At%r%xt # Riemann sum
bInterT <- t(cbind(bt[,,1][,1],bt[,,2][,2]))
# Multiplication from intermediate results
binterM <- t(do.call(cbind, lapply(1:5, function(i) sum(bInter[,i]))))
binterTM <- t(do.call(cbind, lapply(1:5, function(i) sum(bInterT[,i]))))
# Correctness
# Correctness
bInterT
#            [,1]        [,2]        [,3]        [,4]        [,5]
#[1,] -0.05142981  0.02118395 -0.01362231 -0.02374106 -0.01516563
#[2,]  0.16710413 -2.38004921  0.14905054 -3.17821889  0.09874990
bInter
#            [,1]        [,2]        [,3]        [,4]        [,5]
#[1,] -0.05142981  0.02118395 -0.01362231 -0.02374106 -0.01516563
#[2,]  0.16710413 -2.38004921  0.14905054 -3.17821889  0.09874990
b
#            [,1]
#[1,]  0.11567432
#[2,] -2.35886526
#[3,]  0.13542823
#[4,] -3.20195995
#[5,]  0.08358427
binterM
#            [,1]
#[1,]  0.11567432
#[2,] -2.35886526
#[3,]  0.13542823
#[4,] -3.20195995
#[5,]  0.08358427
binterTM
#            [,1]
#[1,]  0.11567432
#[2,] -2.35886526
#[3,]  0.13542823
#[4,] -3.20195995
#[5,]  0.08358427