2015-01-28 20 views
8

Tôi yêu do.call. Tôi thích có thể lưu trữ các đối số hàm trong một danh sách và sau đó tách chúng vào một hàm đã cho.Cách thay thế cho do.call cho các tập dữ liệu lớn

Ví dụ, tôi thường thấy mình sử dụng mô hình này để phù hợp với một danh sách các mô hình dự báo khác nhau, với một số chia sẻ và một số thông số duy nhất cho mỗi mô hình:

library(caret) 
global_args <- list(
    x=iris[,1:3], 
    y=iris[,4], 
    trControl=trainControl(
    method='cv', 
    number=2, 
    returnResamp='final', 
    ) 
) 
global_args$trControl$index <- createFolds(
    global_args$y, 
    global_args$trControl$number 
) 
model_specific_args <- list(
    'lm' = list(method='lm', tuneLength=1), 
    'nn' = list(method='nnet', tuneLength=3, trace=FALSE), 
    'gbm' = list(
    method='gbm', 
    verbose=FALSE, 
    tuneGrid=expand.grid(
     n.trees=1:100, 
     interaction.depth=c(2, 3), 
     shrinkage=c(.1, .01) 
    ) 
) 
) 
list_of_models <- lapply(model_specific_args, function(args){ 
    return(do.call(train, c(global_args, args), quote=TRUE)) 
}) 
resamps <- resamples(list_of_models) 
dotplot(resamps, metric='RMSE') 

global_args chứa đối số là như nhau cho tất cả của các mô hình và model_specific_args chứa danh sách các đối số theo mô hình cụ thể. Tôi vòng qua model_specific_args, nối mỗi phần tử với global_args và sau đó sử dụng do.call để chuyển danh sách đối số cuối cùng cho hàm phù hợp với mô hình.

Trong khi mã này là trực quan thanh lịch, hiệu suất của nó là khủng khiếp: do.call theo nghĩa đen tuần tự toàn bộ tập dữ liệu x dưới dạng văn bản và sau đó chuyển nó đến hàm phù hợp với mô hình. Nếu x là một vài GB dữ liệu, điều này sử dụng một lượng RAM điên rồ và thường không thành công.

print(list_of_models[[1]]$call) 

Có ai cách để vượt qua một danh sách các đối số cho hàm trong R, mà không sử dụng do.call hoặc call?

+0

Bạn đã thử rbind.fill từ gói plyr chưa. Tôi đã không đọc mã để biết nếu sản phẩm cuối cùng là một khung dữ liệu, nhưng nếu như vậy, sau đó rbind.fill là nhanh hơn đáng kể so với do.call tương đương (rbind, ...). Trong các trường hợp khác, tôi cũng đã thành công khi sử dụng Reduce (.) – jimmyb

+0

@jimmyb Tôi không nghĩ 'rbind.fill' hoặc' Reduce' là thích hợp ở đây. Tôi không cố gắng kết hợp 'data.frames', tôi đang cố gắng chuyển danh sách các đối số tới một hàm. – Zach

+0

Có [this] (http://stackoverflow.com/questions/13923301/is-there-a-work-around-for-slow-performance-of-do-callcbind-xts-in-r-2-15) Cứu giúp? – r2evans

Trả lời

1

Dựa trên nhận xét @ r2evans, đây là một giải pháp khả thi: quote() các đối tượng lớn trong danh sách đối số. Sau đó, họ sẽ được lấy từ môi trường toàn cầu khi do.call đánh giá chức năng:

library(caret) 
x <- iris[,1:3] 
y <- iris[,4] 
global_args <- list(
    x=quote(x), 
    y=quote(y), 
    trControl=trainControl(
    method='cv', 
    number=2, 
    returnResamp='final' 
) 
) 
global_args$trControl$index <- createFolds(
    y, 
    global_args$trControl$number 
) 
model_specific_args <- list(
    'lm' = list(method='lm', tuneLength=1), 
    'nn' = list(method='nnet', tuneLength=3, trace=FALSE), 
    'gbm' = list(
    method='gbm', 
    verbose=FALSE, 
    tuneGrid=expand.grid(
     n.trees=1:100, 
     interaction.depth=c(2, 3), 
     shrinkage=c(.1, .01) 
    ) 
) 
) 
list_of_models <- lapply(model_specific_args, function(args){ 
    return(do.call(train, c(global_args, args), quote=FALSE)) 
}) 
print(list_of_models[[1]]$call) 

Kết quả là nhỏ hơn nhiều:

train.default(x = x, y = y, method = "lm", trControl = list(method = "cv", 
    number = 2, repeats = 1, p = 0.75, initialWindow = NULL, 
    horizon = 1, fixedWindow = TRUE, verboseIter = FALSE, returnData = TRUE, 
    returnResamp = "final", savePredictions = FALSE, classProbs = FALSE, 
    summaryFunction = function (data, lev = NULL, model = NULL) 
    { 
     if (is.character(data$obs)) 
      data$obs <- factor(data$obs, levels = lev) 
     postResample(data[, "pred"], data[, "obs"]) 
    }, selectionFunction = "best", preProcOptions = list(thresh = 0.95, 
     ICAcomp = 3, k = 5), index = list(Fold1 = c(6L, 7L, 11L, 
    12L, 13L, 14L, 15L, 16L, 21L, 22L, 25L, 26L, 29L, 32L, 34L, 
    35L, 36L, 37L, 38L, 39L, 40L, 41L, 48L, 49L, 50L, 51L, 52L, 
    54L, 57L, 58L, 59L, 64L, 65L, 66L, 67L, 69L, 70L, 71L, 72L, 
    74L, 78L, 80L, 83L, 84L, 85L, 91L, 92L, 93L, 95L, 98L, 99L, 
    100L, 103L, 105L, 106L, 107L, 109L, 111L, 112L, 116L, 118L, 
    122L, 123L, 124L, 125L, 128L, 130L, 132L, 133L, 135L, 138L, 
    141L, 143L, 144L, 145L, 148L), Fold2 = c(1L, 2L, 3L, 4L, 
    5L, 8L, 9L, 10L, 17L, 18L, 19L, 20L, 23L, 24L, 27L, 28L, 
    30L, 31L, 33L, 42L, 43L, 44L, 45L, 46L, 47L, 53L, 55L, 56L, 
    60L, 61L, 62L, 63L, 68L, 73L, 75L, 76L, 77L, 79L, 81L, 82L, 
    86L, 87L, 88L, 89L, 90L, 94L, 96L, 97L, 101L, 102L, 104L, 
    108L, 110L, 113L, 114L, 115L, 117L, 119L, 120L, 121L, 126L, 
    127L, 129L, 131L, 134L, 136L, 137L, 139L, 140L, 142L, 146L, 
    147L, 149L, 150L)), indexOut = NULL, timingSamps = 0, predictionBounds = c(FALSE, 
    FALSE), seeds = NA, adaptive = list(min = 5, alpha = 0.05, 
     method = "gls", complete = TRUE), allowParallel = TRUE), 
    tuneLength = 1) 

Nó vẫn muốn được tốt đẹp để không phải serialize tất cả các tùy chọn khác Tuy nhiên. Cuộc gọi của mô hình thứ ba nói riêng vẫn rất lớn: print(list_of_models[[3]]$call)

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