подбор линейной смешанной модели к очень большому набору данных

Я хочу запустить смешанную модель (используя lme4::lmer) для 60 млн наблюдений следующего формата; все предикторы/зависимые переменные являются категориальными (факторами), за исключением непрерывной зависимой переменной tc; patient — это группирующая переменная для случайного перехватываемого члена. У меня 64-битная версия R и 16 ГБ ОЗУ, и я работаю с центрального сервера. RStudio — самая последняя версия сервера.

model <- lmer(tc~sex+age+lho+atc+(1|patient),
              data=master,REML=TRUE)

lho sex tc      age         atc patient
18  M   16.61   45-54       H   628143
7   F   10.52   12-15       G   2013855
30  M   92.73   35-44       N   2657693
19  M   24.92   70-74       G   2420965
12  F   17.44   65-69       A   2833610
31  F   7.03    75 and over A   1090322
3   F   28.59   70-74       A   2718649
29  F   4.09    75 and over C   384578
16  F   67.22   65-69       R   1579355
23  F   7.7     70-74       C   896374

Я получаю сообщение об ошибке cannot allocate a vector of 25.5Gb. Мне выделено 40 ГБ на сервере, а я использую 25, так что, думаю, это означает, что мне нужно еще 10 или около того. Я не думаю, что смогу получить дополнительное место.

Я ничего не знаю о параллельной обработке, за исключением того, что в данный момент я использую одно из четырех ядер. Может ли кто-нибудь предложить параллельный код для этой модели или, возможно, другое исправление?


person steve    schedule 16.07.2015    source источник
comment
попробовать MixedModels пакет/библиотеку Дуга Бейтса для Джулии?   -  person Ben Bolker    schedule 16.07.2015
comment
Во-первых, вектор распределения означает выделение оперативной памяти, поэтому дисковая память сервера не имеет значения. Затем вам действительно нужно потратить время на изучение таких пакетов, как parallel и snow и bigdata. В противном случае, даже если кто-то напишет для вас инструмент, вы не поймете, как его модифицировать или найти узкие места в скорости.   -  person Carl Witthoft    schedule 16.07.2015
comment
Спасибо, Бен, я посмотрю.   -  person steve    schedule 16.07.2015
comment
Время работает против меня, Карл, поэтому я публикую вопрос.   -  person steve    schedule 16.07.2015
comment
Посмотрите на свою матрицу дизайна. Я бы предположил, что он огромный. Вы должны тщательно обдумать, подходит ли модель, которую вы пытаетесь подобрать. Например, вам действительно нужен каждый уровень atc? Не могли бы вы смоделировать atc как случайный эффект? Или, возможно, агломерировать atc уровней? Кроме того, вы проверили, что ваши числовые переменные numeric в R? В любом случае распараллеливание не поможет с проблемой памяти. Напротив, поскольку каждому ЦП для выполнения своей задачи потребуется ОЗУ, распараллеливание усугубит проблему.   -  person Roland    schedule 16.07.2015
comment
Спасибо, Роланд. Я ничего не могу потерять на atc. Не думал об этой проблеме с оперативной памятью.   -  person steve    schedule 16.07.2015


Ответы (1)


Как указал Карл Витхофт, стандартные инструменты распараллеливания в R используют модель разделяемой памяти, поэтому они скорее ухудшат, чем улучшат ситуацию (их основная цель — ускорить вычислительные операции задания с использованием нескольких процессоров).

В краткосрочной перспективе вы можете сэкономить немного памяти, рассматривая категориальные предикторы с фиксированным эффектом (age, atc) как случайные эффекты, но заставляя их дисперсии быть большими. Я не знаю, будет ли этого достаточно, чтобы спасти вас или нет; он сильно сожмет матрицу модели с фиксированным эффектом, но кадр модели все равно будет храниться/реплицироваться с объектом модели...

dd1 <- read.table(header=TRUE,
text="lho sex tc      age         atc patient
18  M   16.61   45-54       H   628143
7   F   10.52   12-15       G   2013855
30  M   92.73   35-44       N   2657693
19  M   24.92   70-74       G   2420965
12  F   17.44   65-69       A   2833610
31  F   7.03    75_and_over A   1090322
3   F   28.59   70-74       A   2718649
29  F   4.09    75_and_over C   384578
16  F   67.22   65-69       R   1579355
23  F   7.7     70-74       C   896374")
n <- 1e5
set.seed(101)
dd2 <- with(dd1,
      data.frame(tc=rnorm(n,mean=mean(tc),sd=sd(tc)),
                 lho=round(runif(n,min=min(lho),max=max(lho))),
                 sex=sample(levels(sex),size=n,replace=TRUE),
                 age=sample(levels(age),size=n,replace=TRUE),
                 atc=sample(levels(atc),size=n,replace=TRUE),
                 patient=sample(1:1000,size=n,replace=TRUE)))
library("lme4")
m1 <- lmer(tc~sex+(1|lho)+(1|age)+(1|atc)+(1|patient),
           data=dd2,REML=TRUE)

Случайные эффекты автоматически сортируются в порядке от наибольшего к наименьшему количеству уровней. Следуя механизму, описанному на странице справки ?modular:

lmod <- lFormula(tc~sex+(1|lho)+(1|age)+(1|atc)+(1|patient),
                  data=dd2,REML=TRUE)
names(lmod$reTrms$cnms)  ## ordering
devfun <- do.call(mkLmerDevfun, lmod)
wrapfun <- function(tt,bigsd=1000) {
    devfun(c(tt,rep(bigsd,3)))
}
wrapfun(1)
opt <- optim(fn=wrapfun,par=1,method="Brent",lower=0,upper=1000)
opt$fval <- opt$value  ## rename/copy
res <- mkMerMod(environment(devfun), opt, lmod$reTrms, fr=lmod$fr)
res

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

В долгосрочной перспективе правильным способом решения этой проблемы, вероятно, будет распараллелить ее с помощью модели с распределенной памятью. Другими словами, вы хотели бы распределить данные порциями по разным серверам; использовать механизм, описанный в ?modular, для настройки функции правдоподобия (на самом деле функции REML-критерия), которая дает критерий REML для подмножества данных как функцию параметров; затем запустите центральный оптимизатор, который принимает набор параметров и оценивает критерий REML, отправляя параметры на каждый сервер, получая значения с каждого сервера и добавляя их. Единственные две проблемы, которые я вижу при реализации этого: (1) я на самом деле не знаю, как реализовать вычисления с распределенной памятью в R (на основе этот вводный документ кажется, что Rmpi/doMPI пакеты могут быть правильным путем); (2) в способе реализации lmer по умолчанию параметры с фиксированными эффектами профилируются, а не являются явной частью вектора параметров.

person Ben Bolker    schedule 16.07.2015
comment
Большое спасибо за ваш вклад, Бен. Мне понадобится некоторое время, чтобы разобрать все это, но я попробую. - person steve; 17.07.2015
comment
Только что освободилось дополнительное пространство на сервере, но теперь я получаю это сообщение об ошибке: Ошибка в qr.default(X, tol = tol, LAPACK = FALSE): слишком большая матрица для LINPACK Кто-нибудь может пролить свет на это? - person steve; 17.07.2015
comment
вы можете попробовать traceback(), чтобы увидеть, в чем проблема. Я предполагаю, что вы столкнулись с проблемой на этапе проверки того, что матрица модели с фиксированным эффектом (X) имеет полный ранг. Вы можете пропустить этот шаг (control=lmerControl(check.rankX="ignore")), но я предполагаю, что вскоре после этого у вас возникнут новые проблемы. - person Ben Bolker; 17.07.2015
comment
Спасибо, Бен, вот результат после запуска второй строки, которую вы дали. , LAPACK = FALSE) 5: chkRank.drop.cols(X, kind = rankX.chk, tol = 1e-07) - person steve; 20.07.2015
comment
4: lme4::lFormula(formula = tc ~ пол + возраст + lho + atc + (1 | пациент), data = master, REML = TRUE, control = list(optimizer = bobyqa, restart_edge = TRUE, border.tol = 1e -05, calc.derivs = TRUE, use.last.params = FALSE, checkControl = list(check.nobs.vs.rankZ = игнорировать, check.nobs.vs.nlev = остановить, check.nlev.gtreq.5 = игнорировать , check.nlev.gtr.1 = стоп, check.nobs.vs.nRE = стоп, check.rankX = сообщение+drop.cols, check.scaleX = предупреждение, check.formula.LHS = стоп), checkConv = - person steve; 20.07.2015
comment
list(check.conv.grad = list( action = warning, tol = 0.002, relTol = NULL), check.conv.singular = list(action = ignore, tol = 1e-04), check.conv.hess = list( action = warning, tol = 1e-06)), optCtrl = list())) 3: eval(expr, envir, enclos) 2: eval(mc, parent.frame(1L)) 1: lmer(tc ~ sex + возраст + lho + atc + (1 | пациент), данные = мастер, REML = TRUE - person steve; 20.07.2015
comment
поэтому отключите предупреждение check.conv.grad: check.conv.grad="ignore" в lmerControl(). (И аналогично с любыми другими предварительными проверками, которые не работают из-за нехватки памяти...) - person Ben Bolker; 20.07.2015
comment
Спасибо за помощь, Бен. Все еще застрял, но я собираюсь попробовать еще несколько вещей завтра. - person steve; 20.07.2015