Ответ 1
Я спросил профессора Тревора Хэсти и получил следующий совет:
"Привет Флавио
model.matrix убивает вас. У вас будет 49K факторов, а модельная матрица пытается представить их как контрасты, которые будут иметь 6 столбцовых матриц, поэтому 49 * 6 приблизительно 300K столбцов. Почему бы не сделать двоичные фиктивные переменные (7 на коэффициент) и просто построить это напрямую, не используя model.matrix. Вы можете сохранить 1/7-е место, сохранив это через sparseMatrix (glmnet принимает разреженные матричные форматы) "
Я сделал именно это и отлично работал. Я думаю, что это может быть полезно для других.
В статье с кодом, который появился, возникла эта проблема: http://www.rmining.net/2014/02/25/genetic-data-large-matrices-glmnet/
Чтобы избежать неработающих ссылок, я опубликую часть сообщения здесь:
Проблема с формульным подходом заключается в том, что в целом геномные данные имеют больше столбцов, чем наблюдений. Данные, которые я работал в этом случае, имели 40 000 столбцов и всего 73 наблюдения. Чтобы создать небольшой набор тестовых данных, запустите следующий код:
for(i in 1:50) {
x = rep(letters[2:8], 7000)
y = sample(x=1:49000, size=49000)
data[i,] <- x[y]
}
data <- as.data.frame(data)
x <- c(rep('A', 20), rep('B', 15), rep('C', 15))
y <- sample(x=1:50, size=50)
class = x[y]
data <- cbind(data, class)
Итак, с этим набором данных мы попытаемся установить модель с помощью glmnet():
formula <- as.formula(class ~ .)
X <- model.matrix(formula, data)
model <- cv.glmnet(X, class, standardize=FALSE, family='multinomial', alpha=1, nfolds=10)
И если у вас нет компьютера с большей оперативной памятью, чем у меня, вы, вероятно, будете течь из памяти и дать сбой в R. Решение? Моя первая идея состояла в том, чтобы попробовать sparse.model.matrix(), который создает разреженную матричную модель, используя ту же формулу. К сожалению, это не сработало, потому что даже с разреженной матрицей окончательная модель все еще слишком велика! Интересно, что этот набор данных занимает всего 24 МБ из ОЗУ, но при использовании model.matrix результатом является массив с более чем 1 ГБ.
Решение, которое я нашел, это построить матрицу под рукой. Для этого мы кодируем массив с фиктивными переменными, столбцом по столбцу и сохраняем результат в разреженной матрице. Затем мы будем использовать эту матрицу в качестве входных данных для модели и посмотреть, не будет ли она утечки памяти:
## Creates a matrix using the first column
X <- sparse.model.matrix(~data[,1]-1)
## Check if the column have more then one level
for (i in 2:ncol(data)) {
## In the case of more then one level apply dummy coding
if (nlevels(data[,i])>1) {
coluna <- sparse.model.matrix(~data[,i]-1)
X <- cBind(X, coluna)
}
## Transform fator to numeric
else {
coluna <- as.numeric(as.factor(data[,i]))
X <- cBind(X, coluna)
}
ПРИМЕЧАНИЕ. Обратите внимание на то, как мы используем разреженную матрицу, требуется пакет Matrix. Также обратите внимание, что столбцы подключаются с помощью cBind() вместо cbind().
Полученная таким образом матрица была намного ниже: менее 70 Мб при тестировании. К счастью, glmnet() поддерживает разреженную матрицу, и вы можете запустить модель:
mod.lasso <- cv.glmnet(X, class, standardize=FALSE, family='multinomial', alpha=1, nfolds=10)
Таким образом, вы можете создавать модели с данным типом данных без раздувания памяти и без использования пакетов R для больших наборов данных, таких как bigmemory и ff.