R развертка на разреженной матрице - PullRequest
0 голосов
/ 29 марта 2019

Я пытаюсь применить функцию sweep к разреженной матрице (dgCMatrix).К сожалению, когда я делаю это, я получаю ошибку памяти.Кажется, что развертка расширяет мою разреженную матрицу до полной плотной матрицы.

Если есть простой способ выполнить эту функцию без взрыва моей памяти?

Это то, что я пытаюсьделать.

sparse_matrix <- sweep(sparse_matrix, 1, vector_to_multiply, '*')

1 Ответ

1 голос
/ 29 марта 2019

Я повторяю рекомендацию @ user20650 использовать прямое умножение формы mat * vec, которая умножает каждый столбец вашей матрицы mat на ваш вектор vec путем неявной переработки vec.

Время обработки профилирования

Я понимаю, что ваше главное требование здесь - память, но интересно выполнить microbenchmark сравнение sweep и методов прямого умножения для плотной и разреженной матрицы:

# Sample data
library(Matrix)  
set.seed(2018)
mat <- matrix(sample(c(0, 1), 10^6, replace = T), nrow = 10^3)
mat_sparse <- Matrix(mat, sparse = T)
vec <- 1:dim(mat)[1]

library(microbenchmark)
res <- microbenchmark(
    sweep_dense = sweep(mat, 1, vec, '*'),
    sweep_sparse = sweep(mat_sparse, 1, vec, '*'),
    mult_dense = mat * vec,
    mult_sparse = mat_sparse * vec
)
res
Unit: milliseconds
         expr        min         lq       mean     median        uq      max
  sweep_dense   8.639459  10.038711  14.857274  13.064084  18.07434  32.2172
 sweep_sparse 116.649865 128.111162 162.736864 135.932811 155.63415 369.3997
   mult_dense   2.030882   3.193082   7.744076   4.033918   7.10471 184.9396
  mult_sparse  12.998628  15.020373  20.760181  16.894000  22.95510 201.5509

library(ggplot2)
autoplot(res)

enter image description here

В среднем операции с разреженной матрицей на самом деле немного медленнее, чем с плотной матрицей. Обратите внимание, что прямое умножение быстрее, чем sweep.

Профилирование памяти

Мы можем использовать memprof для профилирования использования памяти различными подходами.

library(profmem)
mem <- list(
    sweep_dense = profmem(sweep(mat, 1, vec, '*')),
    sweep_sparse = profmem(sweep(mat_sparse, 1, vec, '*')),
    mult_dense = profmem(sweep(mat * vec)),
    mult_sparse = profmem(sweep(mat_sparse * vec)))
lapply(mem, function(x) utils:::format.object_size(sum(x$bytes), units = "Mb"))
#$sweep_dense
#[1] "15.3 Mb"
#
#$sweep_sparse
#[1] "103.1 Mb"
#
#$mult_dense
#[1] "7.6 Mb"
#
#$mult_sparse
#[1] "13.4 Mb"

Честно говоря, я удивлен, что отпечаток памяти прямого умножения с разреженной матрицей не меньше, чем у плотной матрицы. Возможно, данные выборки слишком упрощены. Возможно, стоит изучить это с вашими фактическими данными (или их репрезентативным подмножеством).

...