我最近一直在使用xgboost模型:
library(xgboost)
set.seed(23)
data(agaricus.train, package='xgboost')
data(agaricus.test, package='xgboost')
train <- agaricus.train
test <- agaricus.test
bst <- xgboost(
data = train$data, label = train$label, max.depth = 2,
eta = 1, nround = 2,objective = "binary:logistic")
pred <- predict(bst, test$data)
不幸的是,如果您尝试使用save
和load
以及xgboost
型号,结果就是段错误:
f <- tempfile()
saveRDS(bst, f)
bst_new = readRDS(f)
unlink(f)
print(bst_new) #NULL pointer
pred2 <- predict(bst_new, test$data) #This line segfaults
这是因为xgboost模型实际上只是指向内存中C ++对象的指针:R包实际上只是一些C ++代码的薄包装:
> print(bst)
<pointer: 0x10a5ae750>
attr(,"class")
[1] "xgb.Booster"
包作者已经意识到了这一点,并编写了2个自定义函数(xgb.save
和xgb.load
)来保存和加载xgboost模型,但是它们没有能力使用它们那么有用来自基地R的save
和load
。我想出了一个用于保存模型作为R会话的一部分的黑客攻击,但它不是很漂亮:
#Hack to save an xgboost model
f1 <- tempfile()
f2 <- tempfile()
xgb.save(bst, f1)
model_raw_bytes <- readBin(f1, what='raw', file.info(f)[1, "size"])
unlink(f1)
print(head(model_raw_bytes))
saveRDS(model_raw_bytes, f2)
#Hack to load an xgboost
f3 <- tempfile()
model_raw_bytes <- readRDS(f2)
writeBin(model_raw_bytes, f3)
model_2 <- xgb.load(f3)
pred_2 <- predict(model_2, test$data)
all.equal(pred_2, pred)
unlink(f2)
unlink(f3)
有没有办法直接从内存中的某个位置readBin
,而不是从磁盘? (这样可以省去编写临时文件以保存和加载模型)。
更好的是,是否有一种可以在C对象中包装R对象的方法,我可以指导包作者?他们非常愿意接受我对github的评论,如果我能提交公关来使这项工作,我认为他们会接受它。