2011-08-22 35 views
7

Tôi đã tạo một số mẫu ctree (khoảng 40 đến 80) mà tôi muốn đánh giá khá thường xuyên.Làm cách nào để xóa dữ liệu đào tạo khỏi bên ::: mô hình ctree?

Một vấn đề là các đối tượng mô hình rất lớn (40 mô hình yêu cầu nhiều hơn 2.8G bộ nhớ) và có vẻ như tôi lưu trữ dữ liệu đào tạo, có thể là modelname @ data và modelname @ response, chứ không phải chỉ các thông tin có liên quan để dự đoán dữ liệu mới.

Hầu hết các gói học tập R khác có các tùy chọn có thể định cấu hình có bao gồm dữ liệu trong đối tượng mô hình hay không, nhưng tôi không thể tìm thấy bất kỳ gợi ý nào trong tài liệu. Tôi cũng đã cố gắng chỉ định các đối tượng ModelEnv rỗng theo

[email protected] <- new("ModelEnv") 

nhưng không ảnh hưởng đến kích thước của tệp RData tương ứng.

Bất cứ ai cũng biết liệu ctree có thực sự lưu trữ dữ liệu đào tạo và cách xóa tất cả dữ liệu khỏi các mô hình ctree không liên quan đến các dự đoán mới sao cho tôi có thể phù hợp với nhiều người trong bộ nhớ?

Thanks a lot,

Stefan


Cảm ơn bạn đã phản hồi của bạn, đó là đã rất hữu ích.

Tôi đã sử dụng dputstr để xem kỹ đối tượng và thấy rằng không có dữ liệu đào tạo nào được bao gồm trong mô hình, nhưng có khe responses, có vẻ như có nhãn đào tạo và tên gọi. Dù sao, tôi nhận thấy rằng mỗi nút có một vector trọng lượng cho mỗi mẫu đào tạo. Sau một thời gian kiểm tra mã, tôi đã kết thúc googling một chút và tìm thấy những nhận xét sau đây trong nhật ký party NEWS:

  CHANGES IN party VERSION 0.9-13 (2007-07-23) 

o update `mvt.f' 

o improve the memory footprint of RandomForest objects 
    substancially (by removing the weights slots from each node). 

Hóa ra, có một hàm C trong gói bên để loại bỏ những khối lượng gọi R_remove_weights với định nghĩa sau đây:

SEXP R_remove_weights(SEXP subtree, SEXP removestats) { 
    C_remove_weights(subtree, LOGICAL(removestats)[0]); 
    return(R_NilValue); 
} 

nó cũng hoạt động tốt:

# cc is my model object 

sum(unlist(lapply(slotNames(cc), function (x) object.size(slot(cc, x))))) 
# returns: [1] 2521256 
save(cc, file="cc_before.RData") 

.Call("R_remove_weights", [email protected], TRUE, PACKAGE="party") 
# returns NULL and removes weights and node statistics 

sum(unlist(lapply(slotNames(cc), function (x) object.size(slot(cc, x))))) 
# returns: [1] 1521392 
save(cc, file="cc_after.RData") 

Như bạn thấy, nó làm giảm subst kích thước đối tượng ngược lại, từ 2,5MB đến 1,5MB.

gì là lạ, tuy nhiên, là rằng các tập tin rdata tương ứng là điên rồ rất lớn, và không có tác động đối với họ:

$ ls -lh cc* 
-rw-r--r-- 1 user user 9.6M Aug 24 15:44 cc_after.RData 
-rw-r--r-- 1 user user 9.6M Aug 24 15:43 cc_before.RData 

việc giải nén file cho thấy đối tượng 2.5MB để chiếm gần 100MB không gian:

$ cp cc_before.RData cc_before.gz 
$ gunzip cc_before.gz 
$ ls -lh cc_before* 
-rw-r--r-- 1 user user 98M Aug 24 15:45 cc_before 

Bất kỳ ý tưởng nào, điều gì có thể gây ra điều này?

+0

Nếu bạn có thể đăng kết quả của 'dput' lên một đối tượng mẫu nhỏ có thể hữu ích. Nếu bạn sử dụng 'str', bạn có thể xem liệu có dữ liệu huấn luyện được lưu trữ trong đối tượng hay không. –

+0

Lưu ý: Tôi đã gắn thẻ lại câu hỏi và xóa nhãn "bên" vì nó không được xác định rõ trên SO, chắc chắn không bị giới hạn đối với gói R. Tôi đã thêm bộ nhớ quản lý vì điều đó dường như là động lực chính. – Iterator

Trả lời

5

Tôi đã tìm thấy giải pháp cho vấn đề này, vì vậy tôi viết câu trả lời này nếu có ai đó có thể gặp phải vấn đề tương tự. Tôi sẽ mô tả quá trình của tôi, vì vậy nó có thể là một chút rambling, do đó, chịu với tôi.

Không có đầu mối, tôi nghĩ về khe nuking và loại bỏ trọng lượng để có được các đối tượng càng nhỏ càng tốt và ít nhất là tiết kiệm một số bộ nhớ, trong trường hợp không sửa chữa sẽ được tìm thấy. Vì vậy, tôi đã xóa @data@responses làm khởi đầu và dự đoán vẫn ổn mà không có chúng, nhưng không ảnh hưởng đến kích thước tệp .RData.

tôi đã đi theo chiều ngược lại và tạo ra và mô hình trống ctree, chỉ Cắm cây vào nó:

> library(party) 

## create reference predictions for the dataset 
> predictions.org <- treeresponse(c1, d) 

## save tree object for reference 
save(c1, "testSize_c1.RData") 

Kiểm tra kích thước của đối tượng gốc:

$ ls -lh testSize_c1.RData 
-rw-r--r-- 1 user user 9.6M 2011-08-25 14:35 testSize_c1.RData 

Bây giờ, chúng ta hãy tạo một CTree trống và chỉ sao chép cây:

## extract the tree only 
> c1Tree <- [email protected] 

## create empty tree and plug in the extracted one 
> newCTree <- new("BinaryTree") 
> [email protected] <- c1Tree 

## save tree for reference 
save(newCTree, file="testSize_newCTree.RData") 

Đối tượng cây mới này giờ đây nhỏ hơn nhiều er:

$ ls -lh testSize_newCTree.RData 
-rw-r--r-- 1 user user 108K 2011-08-25 14:35 testSize_newCTree.RData 

Tuy nhiên, nó không thể được sử dụng để dự đoán:

## predict with the new tree 
> predictions.new <- treeresponse(newCTree, d) 
Error in [email protected]_distr_response(newdata = newdata, ...) : 
    unused argument(s) (newdata = newdata) 

Chúng tôi không thiết lập các @cond_distr_response, mà có thể gây ra lỗi, do đó sao chép một bản gốc cũng và cố gắng dự đoán một lần nữa:

## extract cond_distr_response from original tree 
> cdr <- [email protected]_distr_response 
> [email protected]_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 

này hoạt động hoàn hảo, nhưng bây giờ kích thước của tập tin rdata là trở lại với giá trị ban đầu của nó:

$ 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 

Đơn giản chỉ cần in khe, cho thấy nó là một chức năng liên kết với một môi trường:

> [email protected]_distr_response 
function (newdata = NULL, mincriterion = 0, ...) 
{ 
    wh <- [email protected]_where(newdata = newdata, mincriterion = mincriterion) 
    response <- [email protected] 
    if (any([email protected]_censored)) { 
     swh <- sort(unique(wh)) 
     RET <- vector(mode = "list", length = length(wh)) 
     resp <- [email protected][[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> 

Vì vậy, câu trả lời cho câu hỏi ban đầu dường như là các phương pháp của đối tượng ràng buộc một môi trường với nó, sau đó được lưu với đối tượng trong tệp RData tương ứng. Điều này cũng có thể giải thích tại sao một số gói được tải khi tệp RData được đọc.

Vì vậy, để loại bỏ môi trường, chúng tôi không thể sao chép các phương pháp, nhưng chúng tôi không thể dự đoán nếu không có chúng. Giải pháp khá "bẩn" là mô phỏng chức năng của các phương thức gốc và gọi trực tiếp mã C bên dưới. Sau khi đào một số thông qua mã nguồn, điều này thực sự là có thể. Khi mã được sao chép ở trên gợi ý, chúng ta cần gọi get_where, xác định nút đầu cuối của cây đã đạt được bằng đầu vào. Sau đó chúng ta cần gọi R_getpredictions để xác định phản hồi từ nút đầu cuối đó cho mỗi mẫu đầu vào.Phần khó khăn là chúng ta cần phải nhận được dữ liệu theo định dạng đầu vào đúng và do đó phải gọi tiền xử lý dữ liệu bao gồm trong 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([email protected]@formula$response[[2]]))), 
        "~", 
        do.call(str_c, as.list(deparse([email protected]@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([email protected]@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 

Chúng tôi bây giờ chỉ cần lưu các cây chiết xuất và chuỗi công thức là có thể dự đoán dữ liệu mới:

> save(c1Tree, org.formula, file="testSize_extractedObjects.RData") 

Chúng ta có thể tiếp tục loại bỏ trọng lượng không cần thiết như mô tả trong câu hỏi được cập nhật trên:

> .Call("R_remove_weights", c1Tree, TRUE, PACKAGE="party") 
> save(c1Tree, org.formula, file="testSize_extractedObjects__removedWeights.RData") 

Bây giờ chúng ta hãy có một cái nhìn tại các fi le sizes again:

$ 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 

Cuối cùng, thay vì (nén) 9.6M, chỉ cần 43K để sử dụng kiểu máy. Bây giờ tôi có thể vừa với tôi trong không gian 3G của mình. Hoan hô!

+0

+1 Đó là một bước tuyệt vời bằng cách trình bày từng bước. Công việc tốt. – Iterator

1

Điều bạn đang tìm kiếm là xóa các vị trí. Một lời cảnh cáo: điều này có thể khá nguy hiểm khi các hàm party hoạt động với đối tượng.

Tuy nhiên, hãy xem slotNames(yourModel). Bạn cũng có thể thử object.size(slot(yourModel), slotNameOfInterest) để kiểm tra kích thước của các vị trí khác nhau. Bạn có thể dễ dàng tạo một bảng được sắp xếp để đảm bảo kích thước của các đối tượng trong mỗi khe.

Trong mọi trường hợp, vị trí cho dataModelEnvFormula (Tôi sẽ gọi đối tượng "MEF") này. Bạn có thể tạo một MEF giả: dummyMEF <- ModelEnvFormula(1 ~ 1) và sau đó gán cho data: slot(yourModel, "data") <- dummyMEF.

Điều đó sẽ nuke rằng vị trí cụ thể đó. Bạn nên xem xét xem có các khe cắm khác đang gây ra nhức đầu về dung lượng lưu trữ hay không - chức năng object.size() sẽ hỗ trợ. Tôi đồng ý rằng thật tuyệt khi có thể bỏ qua dữ liệu đào tạo từ đối tượng mô hình.

Các vấn đề liên quan