20

我在运行具有广泛数据集的 glmnet lasso 时遇到问题。我的数据有 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)

之后,我尝试创建一个 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)

在最后一步(X = model.matrix ...)我内存不足。我能做些什么?

4

2 回答 2

26

我问了 Trevor Hastie 教授,得到了以下建议:

“你好弗拉维奥

model.matrix 正在杀死你。您将有 49K 因子,模型矩阵试图将它们表示为对比,这将是 6 列矩阵,因此 49*6 大约 300K 列。为什么不制作二进制虚拟变量(每个因子 7 个),而无需使用 model.matrix 直接构造它。您可以通过 sparseMatrix 存储它来节省 1/7 的空间(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)

而且,如果您的计算机没有比我的 RAM 更多的计算机,您可能会泄漏内存并在 R 中崩溃。解决方案?我的第一个想法是尝试使用相同公式创建稀疏矩阵模型的sparse.model.matrix() 。不幸的是没有奏效,因为即使使用稀疏矩阵,最终模型仍然太大!有趣的是,这个数据集只占用了 24MB 的 RAM,但是当你使用 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)
}

注意:注意我们如何使用稀疏矩阵,需要 Matrix 包。另请注意,列是使用 cBind () 而不是 cbind () 连接的。

这样生成的矩阵要低得多:我测试时不到 70 Mb。幸运的是 glmnet() 支持稀疏矩阵,您可以运行模型:

mod.lasso <- cv.glmnet(X, class, standardize=FALSE, family='multinomial', alpha=1, nfolds=10)

因此,您可以使用这种类型的数据创建模型,而不会占用内存,也无需为bigmemoryff等大型数据集使用 R 包。

于 2013-06-17T15:53:31.460 回答
6

谁可能感兴趣。我开发了一个名为 R 包biglasso,它适合带有大数据的套索类型模型。它适用于基于bigmemory封装的内存映射(大)设计矩阵,并且可以无缝地适用于数据大于 RAM 的情况。glmnet此外,与使用新提出的特征筛选规则以及更好的实现相比,它的计算和内存效率更高。请查看GitHub 页面了解详细信息,并随时提供任何建议/意见。

于 2016-12-21T05:27:18.617 回答