运行glmnet()的大矩阵

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)

因此,您可以创建具有此类数据的模型,而无需使用内存,也无需使用大型数据集(如bigmemoryff)的 R包.

  • 您也可以尝试使用Matrix :: sparse.model.matrix或MatrixModels :: modelMatrix(*,sparse = TRUE)。 (2认同)

Aar*_*eng 5

对谁可能感兴趣。我开发了一个名为R的软件包biglasso,该软件包适合套索类型的模型和大数据。它与基于bigmemory封装的内存映射(大)设计矩阵配合使用,并且可以无缝处理大于RAM的数据。而且,与glmnet使用新提出的特征筛选规则以及更好的实现方式相比,它具有更高的计算和内存效率。请检查GitHub页面以获取详细信息,并随时提供任何建议/评论。