lm 的内存问题
Memory issue with lm
我有一个包含大约 400 万行和 15 个变量的大型数据框。我正在尝试实施一种模型选择算法,该算法添加了一个变量,该变量导致 lm
模型的 r 平方增幅最大。
以下代码片段是我的函数因数据量大而失败的地方。我试过 biglm
但还是不行。我这里以mtcars
为例,只是为了说明。
library(biglm)
library(dplyr)
data <- mtcars
y <- "mpg"
vars.model <- "cyl"
vars.remaining <- setdiff(names(data), c("mpg", "cyl"))
new.rsq <- sapply(vars.remaining,
function (x) {
vars.test <- paste(vars.model, x, sep="+")
fit.sum <- biglm(as.formula(paste(y, vars.test, sep="~")),
data) %>% summary()
new.rsq <- fit.sum$rsq
})
new.rsq
我不确定 R 在这里如何处理内存,但是 biglm
我的 400 万行数据的输出非常小 (6.6 KB)。打包成sapply
不知道怎么累积到好几GB。非常感谢有关如何优化它的任何提示。
内存使用量上升,因为每次调用 biglm()
都会在内存中复制数据。由于 sapply()
基本上是一个 for 循环,使用 doMC
(或 doParallel
)允许通过内存中数据的单个副本来完成循环。这是一种可能性:
编辑:正如@moho wu 指出的那样,平行拟合有帮助,但还不够。因素比普通字符更有效,所以这也有帮助。然后 ff
可以提供更多帮助,因为它将更大的数据集保存在磁盘上,而不是内存中。我更新了下面的代码,使用 ff
和 doMC
.
使其成为一个完整的玩具示例
library(tidyverse)
library(pryr)
# toy data
df <- sample_n(mtcars, size = 1e7, replace = T)
df$A <- as.factor(letters[1:5])
# get objects / save on disk
all_vars <- names(df)
y <- "mpg"
vars.model <- "cyl"
vars.remaining <- all_vars[-c(1:2)]
save(y, vars.model, vars.remaining, file = "all_vars.RData")
readr::write_delim(df, path = "df.csv", delim = ";")
# close R session and start fresh
library(ff)
library(biglm)
library(doMC)
library(tidyverse)
# read flat file as "ff" ; also read variables
ff_df <- read.table.ffdf(file = "df.csv", sep = ";", header = TRUE)
load("all_vars.RData")
# prepare the "cluster"
nc <- 2 # number of cores to use
registerDoMC(cores = nc)
# make all formula
fo <- paste0(y, "~", vars.model, "+", vars.remaining)
fo <- modify(fo, as.formula) %>%
set_names(vars.remaining)
# fit models in parallel
all_rsq <- foreach(fo = fo) %dopar% {
fit <- biglm(formula = fo, data = ff_df)
new.rsq <- summary(fit)$rsq
}
我的问题的罪魁祸首是我有很多字符列。使用我的原始脚本将它们全部更改为因子后,它工作正常。
data %>%
mutate_if(is.character, as.factor)
@meriops 的回答也不错。如果分解数据框不能解决问题,则可能需要考虑并行处理
我有一个包含大约 400 万行和 15 个变量的大型数据框。我正在尝试实施一种模型选择算法,该算法添加了一个变量,该变量导致 lm
模型的 r 平方增幅最大。
以下代码片段是我的函数因数据量大而失败的地方。我试过 biglm
但还是不行。我这里以mtcars
为例,只是为了说明。
library(biglm)
library(dplyr)
data <- mtcars
y <- "mpg"
vars.model <- "cyl"
vars.remaining <- setdiff(names(data), c("mpg", "cyl"))
new.rsq <- sapply(vars.remaining,
function (x) {
vars.test <- paste(vars.model, x, sep="+")
fit.sum <- biglm(as.formula(paste(y, vars.test, sep="~")),
data) %>% summary()
new.rsq <- fit.sum$rsq
})
new.rsq
我不确定 R 在这里如何处理内存,但是 biglm
我的 400 万行数据的输出非常小 (6.6 KB)。打包成sapply
不知道怎么累积到好几GB。非常感谢有关如何优化它的任何提示。
内存使用量上升,因为每次调用 biglm()
都会在内存中复制数据。由于 sapply()
基本上是一个 for 循环,使用 doMC
(或 doParallel
)允许通过内存中数据的单个副本来完成循环。这是一种可能性:
编辑:正如@moho wu 指出的那样,平行拟合有帮助,但还不够。因素比普通字符更有效,所以这也有帮助。然后 ff
可以提供更多帮助,因为它将更大的数据集保存在磁盘上,而不是内存中。我更新了下面的代码,使用 ff
和 doMC
.
library(tidyverse)
library(pryr)
# toy data
df <- sample_n(mtcars, size = 1e7, replace = T)
df$A <- as.factor(letters[1:5])
# get objects / save on disk
all_vars <- names(df)
y <- "mpg"
vars.model <- "cyl"
vars.remaining <- all_vars[-c(1:2)]
save(y, vars.model, vars.remaining, file = "all_vars.RData")
readr::write_delim(df, path = "df.csv", delim = ";")
# close R session and start fresh
library(ff)
library(biglm)
library(doMC)
library(tidyverse)
# read flat file as "ff" ; also read variables
ff_df <- read.table.ffdf(file = "df.csv", sep = ";", header = TRUE)
load("all_vars.RData")
# prepare the "cluster"
nc <- 2 # number of cores to use
registerDoMC(cores = nc)
# make all formula
fo <- paste0(y, "~", vars.model, "+", vars.remaining)
fo <- modify(fo, as.formula) %>%
set_names(vars.remaining)
# fit models in parallel
all_rsq <- foreach(fo = fo) %dopar% {
fit <- biglm(formula = fo, data = ff_df)
new.rsq <- summary(fit)$rsq
}
我的问题的罪魁祸首是我有很多字符列。使用我的原始脚本将它们全部更改为因子后,它工作正常。
data %>%
mutate_if(is.character, as.factor)
@meriops 的回答也不错。如果分解数据框不能解决问题,则可能需要考虑并行处理