我问了Trevor Hastie教授并得到了以下建议:
"你好Flavio
model.matrix会使你的程序崩溃。
你将拥有49K个因子,而model matrix试图将它们表示为对比度,这将是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的数组。
我找到的解决方案是手动构建矩阵。为此,我们逐列对虚拟变量进行编码,并将结果存储在稀疏矩阵中。然后,我们将使用该矩阵作为输入来运行模型,看看是否会出现内存泄漏:
X <- sparse.model.matrix(~data[,1]-1)
for (i in 2:ncol(data)) {
if (nlevels(data[,i])>1) {
coluna <- sparse.model.matrix(~data[,i]-1)
X <- cBind(X, coluna)
}
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包来处理大型数据集。