R: Самый эффективный способ для хранения с файловой поддержкой большой разреженной 3-сторонней тензорной или разреженной расширенной матрицы

Я хотел бы иметь эффективную платформу в R для хранения на основе файлов большого трехстороннего тензора длинных целых чисел (15000 (измерение времени) x 500000 (2-е измерение) x 500 (пример, 3D-измерение)), используя как расширенная матрица измерения строки / времени (т.е. использующая матрицу 15000*500000 x 500), и мне нужны функциональные возможности для эффективного извлечения определенных разделов этой матрицы для обработки в памяти, а также обновления определенных разделов после обработки. Для плотных матриц я могу использовать bigmatrix пакет для этого, но в моем последнем приложении матрицы разрежены (примерно с 99% нулей), и, как я понимаю bigmatrix в настоящее время не поддерживает разреженные матрицы. Кто-нибудь знает какие-либо другие варианты, которые я мог бы использовать для этого в R? (пакеты ff и dplyr, поддерживаемый базой данных на диске, которую я понимаю, также не поддерживают разреженные матрицы или тензоры на данный момент) Есть мысли?

Пример кода для случая плотного тензора / расширенной матрицы (но который также должен работать для разреженных тензоров / матриц, которые на 1000 больше)

# example problem size
NRows = 15000 # time dimension
NCols = 500 # 2nd dimension, 1000x larger & sparse in final application 
NSamples = 20 # sample dimension, 500 in reality, testing with 20 here

# just filling with a constant integer here, in reality data is read in from netcdf file
# in final application data will be 1000x larger & sparse, with 99% zeros

getsamplematrix = function(r=NRows,c=NCols) matrix(1L, nrow=r, ncol=c) 
### 1. Using bigmemory as backend
library(bigmemory)

## step 1: store tensor in row/time dimension augmented bigmemory matrix
putdata = function (NRows, NCols, NSamples) {
  data = big.matrix(NRows*NSamples, NCols, type = "integer",
    backingfile = "data.bin", descriptorfile = "data.desc",
    backingpath = getwd() )

  for (i in 1:NSamples) {
    data[(1+(i-1)*NRows):(i*NRows), 1:NCols] = getsamplematrix(r = NRows, c = NCols)
  }
  attr(data, "NRows") = NRows
  return(data)
}
system.time(data <- putdata(NRows,NCols,NSamples)) # 23.28 s for 20 matrices


## step 2: get subset of time slices from all samples and store this in 3-way tensor/array S (for in-memory processing)
getsubtensor = function(data, timeindices, cols, samples) { 
  S = array(dim=c(length(timeindices),length(cols),length(samples))) # preallocate array
  nrows = attr(data,"NRows")
  for (i in samples) { 
    S[timeindices,cols,i] = data[((1+(i-1)*nrows):(i*nrows))[timeindices],cols]
  }
  return(S) }
# example: get time indices 1:100 from all samples
system.time(S <- getsubtensor(data, 1:100, 1:NCols, 1:NSamples)) # 0.04 s
dim(S)


## step 3: update subtensor S at given positions in original disk-mapped data after some processing
updatesubtensor = function(data, S, timeindices, cols, samples) { 
  nrows = attr(data,"NRows")
  for (i in samples) { 
    data[((1+(i-1)*nrows):(i*nrows))[timeindices],cols] = S[timeindices,cols,i] 
  }
  return(data) }
S2 <- S*2L # example, processing would be done here
system.time(data <- updatesubtensor(data, S2, 1:100, 1:NCols, 1:NSamples)) # 0.17s

0 ответов

Другие вопросы по тегам