2013-11-26 3 views
1

Я пытаюсь использовать пакет снега для оценки эластичной модели сети в R, но я не могу понять, как заставить функцию прогнозирования работать через несколько узлов в кластере. Приведенный ниже код содержит как временную точку отсчета и фактический код продуцирующие ошибки:Оценка параллельной модели R

############## 
#Snow example# 
############## 

library(snow) 
library(glmnet) 
library(mlbench) 

data(BostonHousing) 
BostonHousing$chas<-as.numeric(BostonHousing$chas) 

ind<-as.matrix(BostonHousing[,1:13],col.names=TRUE) 
dep<-as.matrix(BostonHousing[,14],col.names=TRUE) 

fit_lambda<-cv.glmnet(ind,dep) 

#fit elastic net 
fit_en<<-glmnet(ind,dep,family="gaussian",alpha=0.5,lambda=fit_lambda$lambda.min) 

ind_exp<-rbind(ind,ind) 

#single thread baseline 
i<-0 
while(i < 2000){ 
    ind_exp<-rbind(ind_exp,ind) 
    i = i+1 
    } 

system.time(st<-predict(fit_en,ind_exp)) 

#formula for parallel execution 
pred_en<-function(x){ 
    x<-as.matrix(x) 
    return(predict(fit_en,x)) 
    } 

#make the cluster 
cl<-makeSOCKcluster(4) 
clusterExport(cl,"fit_en") 
clusterExport(cl,"pred_en") 

#parallel baseline 
system.time(mt<-parRapply(cl,ind_exp,pred_en)) 

я смог распараллелить через разветвление на коробке Linux с использованием многоядерной, но я в конечном итоге приходится использовать довольно неэффективные mclapply в сочетании с unlist и искал лучший способ сделать это со снегом (что, кстати, будет работать как на моем компьютере с ОС Windows, так и на моих Linux-серверах prod). Спасибо, ТАК.

ответ

2

Начну с того, что функция predict.glmnet не кажется достаточно вычислительной, чтобы ее можно было распараллелить. Но это интересный пример, и мой ответ может быть вам полезен, даже если этот конкретный случай не стоит распараллеливать.

Основная проблема заключается в том, что функция parRapply представляет собой параллельную оболочку вокруг apply, которая, в свою очередь, вызывает вашу функцию в строках подматриц, чего вы не хотите. Вы хотите, чтобы ваша функция вызывалась непосредственно на подматрицы. Снег не содержит удобную функцию, которая делает это, но это легко написать одно:

rowchunkapply <- function(cl, x, fun, ...) { 
    do.call('rbind', clusterApply(cl, splitRows(x, length(cl)), fun, ...)) 
} 

Другая проблема в вашем примере является то, что вам нужно загрузить glmnet на рабочих, так что правильно предсказать функция вызывается. Вам также не нужно явно экспортировать функцию pred_en, так как это обрабатывается для вас.

Вот моя версия вашего примера:

library(snow) 
library(glmnet) 
library(mlbench) 

data(BostonHousing) 
BostonHousing$chas <- as.numeric(BostonHousing$chas) 
ind <- as.matrix(BostonHousing[,1:13], col.names=TRUE) 
dep <- as.matrix(BostonHousing[,14], col.names=TRUE) 
fit_lambda <- cv.glmnet(ind, dep) 
fit_en <- glmnet(ind, dep, family="gaussian", alpha=0.5, 
       lambda=fit_lambda$lambda.min) 
ind_exp <- do.call("rbind", rep(list(ind), 2002)) 

# make and initialize the cluster 
cl <- makeSOCKcluster(4) 
clusterEvalQ(cl, library(glmnet)) 
clusterExport(cl, "fit_en") 

# execute a function on row chunks of x and rbind the results 
rowchunkapply <- function(cl, x, fun, ...) { 
    do.call('rbind', clusterApply(cl, splitRows(x, length(cl)), fun, ...)) 
} 

# worker function 
pred_en <- function(x) { 
    predict(fit_en, x) 
} 
mt <- rowchunkapply(cl, ind_exp, pred_en) 

Вы также можете быть заинтересованы в использовании cv.glmnetparallel варианта, который использует пакет Еогеаспа.

Смежные вопросы