Недостаточно памяти при использовании «внешнего» при решении моего большого нормального уравнения для оценки методом наименьших квадратов

Рассмотрим следующий пример в R:

x1 <- rnorm(100000)
x2 <- rnorm(100000)
g <- cbind(x1, x2, x1^2, x2^2)
gg <- t(g) %*% g
gginv <- solve(gg)
bigmatrix <- outer(x1, x2, "<=")
Gw <- t(g) %*% bigmatrix
beta <- gginv %*% Gw
w1 <- bigmatrix - g %*% beta

Если я попытаюсь запустить такую ​​штуку на своем компьютере, она выдаст ошибку памяти (потому что bigmatrix слишком велика).

Знаете ли вы, как я могу добиться того же, не сталкиваясь с этой проблемой?


person user17645    schedule 03.10.2016    source источник


Ответы (1)


Это задача наименьших квадратов со 100 000 ответов. Ваш bigmatrix — это ответ (матрица), beta — это коэффициент (матрица), а w1 — остаток (матрица).

bigmatrix, а также w1, если они сформированы явно, будут стоить

(100,000 * 100,000 * 8) / (1024 ^ 3) = 74.5 GB

Это слишком много.

Поскольку оценка для каждого ответа независима, нет необходимости формировать bigmatrix за один раз и пытаться сохранить ее в оперативной памяти. Мы можем просто формировать его плитка за плиткой и использовать итеративную процедуру: формировать плитку, использовать плитку, а затем отбросить ее. Например, ниже рассматривается плитка размерности 100,000 * 2,000 с объемом памяти:

(100,000 * 2,000 * 8) / (1024 ^ 3) = 1.5 GB

Благодаря такой итеративной процедуре использование памяти эффективно контролируется.

x1 <- rnorm(100000)
x2 <- rnorm(100000)
g <- cbind(x1, x2, x1^2, x2^2)
gg <- crossprod(g)    ## don't use `t(g) %*% g`
## we also don't explicitly form `gg` inverse

## initialize `beta` matrix (4 coefficients for each of 100,000 responses)
beta <- matrix(0, 4, 100000)

## we split 100,000 columns into 50 tiles, each with 2000 columns
for (i in 1:50) {
   start <- 2000 * (i-1) + 1    ## chunk start
   end <- 2000 * i    ## chunk end
   bigmatrix <- outer(x1, x2[start:end], "<=")
   Gw <- crossprod(g, bigmatrix)    ## don't use `t(g) %*% bigmatrix`
   beta[, start:end] <- solve(gg, Gw)
   }

Обратите внимание, не пытайтесь вычислить остаточную матрицу w1, так как это будет стоить 74,5 ГБ. Если вам понадобится остаточная матрица в дальнейшей работе, вы все равно должны попытаться разбить ее на тайлы и работать один за другим.

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

person Zheyuan Li    schedule 03.10.2016