Fla*_*ros 20 r lasso-regression bigdata glmnet model.matrix
我有一个问题,用宽数据集运行glmnet套索.我的数据N = 50,但p> 49000,所有因素.所以要运行glmnet,我必须创建一个model.matrix,但是当我调用model.matrix(formula,data)时,我的内存耗尽,其中formula = Class~.
作为一个工作示例,我将生成一个数据集:
data <- matrix(rep(0,50*49000), nrow=50)
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)
Run Code Online (Sandbox Code Playgroud)
之后,我尝试创建一个model.matrix进入glmnet.
formula <- as.formula(class ~ .)
X = model.matrix(formula, data)
model <- cv.glmnet(X, class, standardize=FALSE, family='multinomial', alpha=1, nfolds=10)
Run Code Online (Sandbox Code Playgroud)
在最后一步(X = model.matrix ...),我的内存不足.我能做什么?
Fla*_*ros 25
我问Trevor Hastie教授并收到以下建议:
"弗拉维奥你好
model.matrix杀了你.您将拥有49K因子,模型矩阵试图将它们表示为对比,这将是6列矩阵,因此49*6约300K列.为什么不制作二进制虚拟变量(每个因子7个),只需直接构造它而不使用model.matrix.通过sparseMatrix(glmnet接受稀疏矩阵格式)存储它可以节省1/7的空间"
我做到了这一点,工作得很好.我认为这对其他人有用.
一篇带有代码的文章来自这个问题: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)
Run Code Online (Sandbox Code Playgroud)
因此,使用此数据集,我们将尝试使用glmnet()拟合模型:
formula <- as.formula(class ~ .)
X <- model.matrix(formula, data)
model <- cv.glmnet(X, class, standardize=FALSE, family='multinomial', alpha=1, nfolds=10)
Run Code Online (Sandbox Code Playgroud)
如果你没有比我的RAM更多的计算机,你可能会泄漏内存并在R中崩溃.解决方案?我的第一个想法是尝试使用相同公式创建稀疏矩阵模型的sparse.model.matrix().遗憾的是没有用,因为即使用稀疏矩阵,最终的模型仍然太大了!有趣的是,这个数据集仅占用RAM的24MB,但是当你使用model.matrix时,结果是一个超过1Gb的数组.
我找到的解决方案是手头构建矩阵.为此,我们使用虚拟变量逐列对数组进行编码,并将结果存储在稀疏矩阵中.然后我们将使用此矩阵作为模型的输入,并查看它是否不会泄漏内存:
## 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)
}
Run Code Online (Sandbox Code Playgroud)
注意:请注意我们如何使用需要Matrix包的稀疏矩阵.另请注意,使用cBind()而不是cbind()连接列.
由此产生的基质低得多:我测试时低于70 Mb.幸运的是,glmnet()支持稀疏矩阵,您可以运行模型:
mod.lasso <- cv.glmnet(X, class, standardize=FALSE, family='multinomial', alpha=1, nfolds=10)
Run Code Online (Sandbox Code Playgroud)
因此,您可以创建具有此类数据的模型,而无需使用内存,也无需使用大型数据集(如bigmemory和ff)的 R包.