我有一个大约500G的数据库。它由16个表组成,每个表包含2或3列(第一列可以丢弃(和1375328760行。我需要在h2o中将所有表连接为一个数据帧,因为它们是在XGB模型中运行预测所必需的。我曾尝试使用as.h2o将单个sql表转换到h2o环境中,并将它们一次绑定2或3个表,直到它们成为一个数据集。然而,在转换了4个表后,我得到了"超过GC开销限制:java.lang.OutOfMemoryError"。有办法绕过这个吗?我的机器规格是124G RAM、OS(Rhel 7.8(、Root(1tb(、Home(600G(和2TB外部硬盘。该模型在本地机器上运行,最大_mem_size设置为100G。代码的详细信息如下。
library(data.table)
library(h2o)
h2o.init(
nthreads=14,
max_mem_size = "100G")
h2o.removeAll()
setwd("/home/stan/Documents/LUR/era_aq")
l1.hex <- as.h2o(d2)
l2.hex <- as.h2o(lai)
test_l1.hex <-h2o.cbind(l1.hex,l2.hex[,-1])
h2o.rm (l1.hex,l2.hex)
l3.hex <- as.h2o(lu100)
l4.hex <- as.h2o(lu1000)
test_l2.hex <-h2o.cbind(l3.hex,l4.hex[,-1])
h2o.rm(l3.hex,l4.hex)
l5.hex <- as.h2o(lu1250)
l6.hex <- as.h2o(lu250)
test_l3.hex <-h2o.cbind(l5.hex,l6.hex[,-1])
h2o.rm(l5.hex,l6.hex)
l7.hex <- as.h2o(pbl)
l8.hex <- as.h2o(msl)
test_l4.hex <-h2o.cbind(l7.hex,l8.hex[,-1])
h2o.rm(ll7.hex,l8.hex)
test.hex <-h2o.cbind(test_l1.hex,test_l2.hex[,-1],test_l3.hex[,-1],test_l4.hex[,-1])
test <- test.hex[,-1]
test[1:3,]```
首先,正如Tom在评论中所说,你需要一艘更大的船。H2O将所有数据保存在内存中,通常你需要3到4倍的数据大小才能用它做任何有用的事情。500GB的数据集意味着你需要集群的总内存为1.5-2TB。
(H2O存储压缩后的数据,我认为sqlite不会,在这种情况下,您可能只需要1TB就可以了。(
其次,as.h2o()
是一种加载大数据集的低效方法。将要发生的是,您的数据集加载到R的内存空间中,然后将其保存到csv文件中,然后该csv文件通过TCP/IP流式传输到H2O进程。
因此,更好的方法是直接从sqlite导出到csv文件。然后使用h2o.importFile()
将csv文件加载到H2O中。
h2o.cbind()
还将涉及大量的复制。如果你能在导入之前找到一个工具或脚本来列绑定csv文件,这可能会更有效。快速搜索找到了csvkit,但我不确定它是否需要将文件加载到内存中,或者是否可以完全在磁盘上处理文件。
由于内存非常昂贵,并且所有R都在RAM中运行,因此请避免在全局环境中存储大型助手data.table
和h20
对象。考虑设置一个函数以生成一个列表进行编译,当函数超出范围时,该列表将删除临时对象。理想情况下,您可以直接从文件源构建h2o
对象:
# BUILD LIST OF H20 OBJECTS WITHOUT HELPER COPIES
h2o_list <- lapply(list_of_files, function(f) as.h2o(data.table::fread(f))[-1])
# h2o_list <- lapply(list_of_files, function(f) h2o.importFile(f)[-1])
# CBIND ALL H20 OBJECTS
test.h2o <- do.call(h2o.cbind, h2o_list)
或者甚至将这两行与命名函数结合起来,而不是使用匿名函数。然后,处理后只剩下最后一个对象。
build_h2o <- function(f) as.h2o(data.table::fread(f))[-1])
# build_h2o <- function(f) h2o.importFile(f)[-1]
test.h2o <- do.call(h2o.cbind, lapply(list_of_files, build_h2o))
对于一些需要保留或不保留第一列的数据集,使用if
扩展函数。
build_h2o <- function(f) {
if (grepl("lai|lu1000|lu250|msl", f)) { tmp <- fread(f)[-1] }
else { tmp <- fread(f) }
return(as.h2o(tmp))
}
最后,如果可能的话,利用data.table
方法,如cbindlist
:
final_dt <- cbindlist(lapply(list_of_files, function(f) fread(f)[-1]))
test.h2o <- as.h2o(final_dt)
rm(final_dt)
gc()