Я нашел решение проблемы под рукой, поэтому я пишу этот ответ, если кто-то может столкнуться с той же проблемой. Я опишу свой процесс, так что он может быть немного бессвязным, так что терпите меня.
Понятия не имею, я думал об обнулении слотов и удалении весов, чтобы получить как можно меньше объектов и, по крайней мере, сэкономить память, если не будет найдено исправлений. Поэтому я удалил @data
и @responses
в качестве начала, и предсказание без них прошло хорошо, но никак не повлияло на размер файла .RData.
Я пошел наоборот и создал и пустую модель ctree, просто вставив в нее дерево:
> library(party)
## create reference predictions for the dataset
> predictions.org <- treeresponse(c1, d)
## save tree object for reference
save(c1, "testSize_c1.RData")
Проверка размера исходного объекта:
$ ls -lh testSize_c1.RData
-rw-r--r-- 1 user user 9.6M 2011-08-25 14:35 testSize_c1.RData
Теперь давайте создадим пустое дерево CTree и скопируем только дерево:
## extract the tree only
> c1Tree <- c1@tree
## create empty tree and plug in the extracted one
> newCTree <- new("BinaryTree")
> newCTree@tree <- c1Tree
## save tree for reference
save(newCTree, file="testSize_newCTree.RData")
Этот новый объект дерева теперь намного меньше:
$ ls -lh testSize_newCTree.RData
-rw-r--r-- 1 user user 108K 2011-08-25 14:35 testSize_newCTree.RData
Однако его нельзя использовать для предсказания:
## predict with the new tree
> predictions.new <- treeresponse(newCTree, d)
Error in object@cond_distr_response(newdata = newdata, ...) :
unused argument(s) (newdata = newdata)
Мы не установили @cond_distr_response
, что может привести к ошибке, поэтому скопируйте и оригинал и попробуйте снова сделать прогноз:
## extract cond_distr_response from original tree
> cdr <- c1@cond_distr_response
> newCTree@cond_distr_response <- cdr
## save tree for reference
save(newCTree, file="testSize_newCTree_with_cdr.RData")
## predict with the new tree
> predictions.new <- treeresponse(newCTree, d)
## check correctness
> identical(predictions.org, predictions.new)
[1] TRUE
Это прекрасно работает, но теперь размер файла RData вернулся к своему первоначальному значению:
$ ls -lh testSize_newCTree_with_cdr.RData
-rw-r--r-- 1 user user 9.6M 2011-08-25 14:37 testSize_newCTree_with_cdr.RData
Простая печать слота показывает, что это функция, привязанная к среде:
> c1@cond_distr_response
function (newdata = NULL, mincriterion = 0, ...)
{
wh <- RET@get_where(newdata = newdata, mincriterion = mincriterion)
response <- object@responses
if (any(response@is_censored)) {
swh <- sort(unique(wh))
RET <- vector(mode = "list", length = length(wh))
resp <- response@variables[[1]]
for (i in 1:length(swh)) {
w <- weights * (where == swh[i])
RET[wh == swh[i]] <- list(mysurvfit(resp, weights = w))
}
return(RET)
}
RET <- .Call("R_getpredictions", tree, wh, PACKAGE = "party")
return(RET)
}
<environment: 0x44e8090>
Таким образом, ответ на первоначальный вопрос состоит в том, что методы объекта связывают с ним среду, которая затем сохраняется вместе с объектом в соответствующем файле RData. Это также может объяснить, почему несколько пакетов загружаются при чтении файла RData.
Таким образом, чтобы избавиться от окружающей среды, мы не можем копировать методы, но мы также не можем прогнозировать без них. Довольно «грязное» решение состоит в том, чтобы эмулировать функциональность исходных методов и напрямую вызывать код на языке C. После некоторого изучения исходного кода это действительно возможно. Как видно из кода, скопированного выше, нам нужно вызвать get_where
, который определяет конечный узел дерева, достигнутый входом. Затем нам нужно вызвать R_getpredictions
, чтобы определить ответ от этого терминального узла для каждой входной выборки. Сложность в том, что нам нужно получить данные в правильном формате ввода и, таким образом, вызвать предварительную обработку данных, включенную в ctree:
## create a character string of the formula which was used to fit the free
## (there might be a more neat way to do this)
> library(stringr)
> org.formula <- str_c(
do.call(str_c, as.list(deparse(c1@data@formula$response[[2]]))),
"~",
do.call(str_c, as.list(deparse(c1@data@formula$input[[2]]))))
## call the internal ctree preprocessing
> data.dpp <- party:::ctreedpp(as.formula(org.formula), d)
## create the data object necessary for the ctree C code
> data.ivf <- party:::initVariableFrame.df(data.dpp@menv@get("input"),
trafo = ptrafo)
## now call the tree traversal routine, note that it only requires the tree
## extracted from the @tree slot, not the whole object
> nodeID <- .Call("R_get_nodeID", c1Tree, data.ivf, 0, PACKAGE = "party")
## now determine the respective responses
> predictions.syn <- .Call("R_getpredictions", c1Tree, nodeID, PACKAGE = "party")
## check correctness
> identical(predictions.org, predictions.syn)
[1] TRUE
Теперь нам нужно только сохранить извлеченное дерево и строку формулы, чтобы иметь возможность предсказывать новые данные:
> save(c1Tree, org.formula, file="testSize_extractedObjects.RData")
Мы можем дополнительно удалить ненужные веса, как описано в обновленном вопросе выше:
> .Call("R_remove_weights", c1Tree, TRUE, PACKAGE="party")
> save(c1Tree, org.formula, file="testSize_extractedObjects__removedWeights.RData")
Теперь давайте снова посмотрим на размеры файлов:
$ ls -lh testSize_extractedObjects*
-rw-r--r-- 1 user user 109K 2011-08-25 15:31 testSize_extractedObjects.RData
-rw-r--r-- 1 user user 43K 2011-08-25 15:31 testSize_extractedObjects__removedWeights.RData
Наконец, вместо (сжатого) 9,6 МБ для использования модели требуется только 43 КБ. Теперь я должен быть в состоянии разместить столько, сколько я хочу в моем пространстве кучи 3G. Ура!