Подтвердить что ты не робот

Умножить строки матрицы на вектор?

Я оптимизирую функцию, и я хочу избавиться от медленных циклов. Я ищу более быстрый способ умножить каждую строку матрицы на вектор.

Любые идеи?

EDIT:

Я не ищу "классическое" умножение.

Eg. У меня есть матрица, которая имеет 23 столбца и 25 строк и вектор длиной 23. В результате я хочу иметь матрицу 25x23, которая имеет каждую строку, умноженную на вектор.

4b9b3361

Ответ 1

Я думаю, что вы ищете sweep().

> (mat <- matrix(rep(1:3,each=5),nrow=3,ncol=5,byrow=TRUE))
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    1    1    1    1
[2,]    2    2    2    2    2
[3,]    3    3    3    3    3
> vec <- 1:5
> sweep(mat,MARGIN=2,vec,`*`)
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    2    3    4    5
[2,]    2    4    6    8   10
[3,]    3    6    9   12   15

Это была одна из основных функций R, хотя на протяжении многих лет были сделаны улучшения.

Ответ 2

> MyMatrix <- matrix(c(1,2,3, 11,12,13), nrow = 2, ncol=3, byrow=TRUE)
> MyMatrix
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]   11   12   13
> MyVector <- c(1:3)
> MyVector
[1] 1 2 3

Вы можете использовать либо:

> t(t(MyMatrix) * MyVector)
     [,1] [,2] [,3]
[1,]    1    4    9
[2,]   11   24   39

или

> MyMatrix %*% diag(MyVector)
     [,1] [,2] [,3]
[1,]    1    4    9
[2,]   11   24   39

Ответ 3

На самом деле sweep не самый быстрый вариант на моем компьютере:

MyMatrix <- matrix(c(1:1e6), ncol=1e4, byrow=TRUE)
MyVector <- c(1:1e4)

Rprof(tmp <- tempfile(),interval = 0.001)
t(t(MyMatrix) * MyVector) # first option
Rprof()
MyTimerTranspose=summaryRprof(tmp)$sampling.time
unlink(tmp)

Rprof(tmp <- tempfile(),interval = 0.001)
MyMatrix %*% diag(MyVector) # second option
Rprof()
MyTimerDiag=summaryRprof(tmp)$sampling.time
unlink(tmp)

Rprof(tmp <- tempfile(),interval = 0.001)
sweep(MyMatrix ,MARGIN=2,MyVector,`*`)  # third option
Rprof()
MyTimerSweep=summaryRprof(tmp)$sampling.time
unlink(tmp)

Rprof(tmp <- tempfile(),interval = 0.001)
t(t(MyMatrix) * MyVector) # first option again, to check order 
Rprof()
MyTimerTransposeAgain=summaryRprof(tmp)$sampling.time
unlink(tmp)

MyTimerTranspose
MyTimerDiag
MyTimerSweep
MyTimerTransposeAgain

Это дает:

> MyTimerTranspose
[1] 0.04
> MyTimerDiag
[1] 40.722
> MyTimerSweep
[1] 33.774
> MyTimerTransposeAgain
[1] 0.043

В качестве самой медленной опции второй вариант достигает предела памяти (2046 МБ). Однако, учитывая оставшиеся варианты, двойная транспозиция, по-моему, намного лучше, чем sweep.


Edit

Просто повторяйте меньшее количество данных несколько раз:

MyMatrix <- matrix(c(1:1e3), ncol=1e1, byrow=TRUE)
MyVector <- c(1:1e1)
n=100000

[...]

for(i in 1:n){
# your option
}

[...]

> MyTimerTranspose
[1] 5.383
> MyTimerDiag
[1] 6.404
> MyTimerSweep
[1] 12.843
> MyTimerTransposeAgain
[1] 5.428

Ответ 4

Для скорости можно создать матрицу из вектора перед умножением

mat <-  matrix(rnorm(1e6), ncol=1e4)
vec <- c(1:1e4)
mat * matrix(vec, dim(mat)[1], length(vec))

library(microbenchmark)
microbenchmark(
  transpose = t(t(mat) * vec), 
  make_matrix = mat * matrix(vec, dim(mat)[1], length(vec), byrow = TRUE),
  sweep = sweep(mat,MARGIN=2,vec,'*'))

#Unit: milliseconds
#        expr       min        lq      mean    median        uq      max neval
#   transpose 10.554500 11.459181 14.344774 11.917376 16.235005 86.74867   100
# make_matrix  4.104297  4.537571  6.338247  4.767895  8.537845 13.52492   100
#       sweep  8.332441  8.743813 13.396708  9.175766 14.843811 83.42181   100

Ответ 5

Google "R matrix multipcation" дает "Матричное умножение" , в котором описывается оператор% *% и сказано:" Умножает две матрицы, если они Если один аргумент является вектором, ему будет присвоена либо матрица строк, либо столбцов, чтобы сделать два аргумента совместимыми. Если оба они являются векторами, он вернет внутреннее произведение (в виде матрицы).