我问了 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)
因此,您可以使用这种类型的数据创建模型,而不会占用内存,也无需为bigmemory和ff等大型数据集使用 R 包。