2017-01-12 8 views
1

У меня возникли проблемы с пониманием того, как сделать мой код параллельным. Мое желание состоит в том, чтобы найти 3 вектора из матрицы из 20, которые производят ближайшую линейную регрессию к моей измеренной переменной (что означает, что в общей сложности 1140 различных комбинаций). В настоящее время я смог использовать 3 вложенные петли foreach, которые возвращают лучшие векторы. Однако мое желание состоит в том, чтобы сделать внешний цикл (или все из них?) Работать параллельно. Любая помощь будет оценена!Использование «foreach» для запуска на всех возможных перестановках в R

Вот мой код:

NIR= matrix(rexp(100, rate=0.01),ncol=20, nrow = 4) #Creating the matrix with 20 vectors 
colnames(NIR)=c(1:20) 

S.measured=c(7,9,11,13) #Measured variable 

bestvectors<-matrix(data=NA,ncol = 3+1, nrow= 1) #creating a vector to save in it the best results 

###### Parallel stuff 
no_cores <- detectCores() - 1 
cl<-makeCluster(no_cores) 
registerDoParallel(cl) 

#nested foreach loop to exhaustively find the best vectors 
foreach(i=1:numcols) %:% 
    foreach(j=i:numcols) %:% 
    foreach(k=j:numcols) %do% { 
     if(i==j|i==k|j==k){ #To prevent same vector from being used twice 
     } 
     else{ 
     lm<-lm(S.measured~NIR[,c(i,j,k)]-1) # package that calculates the linear regression 
     S.pred<-as.matrix(lm$fitted.values) # predicted vector to be compared with the actual measured one 
     error<-sqrt(sum(((S.pred-S.measured)/S.measured)^2)) # The 'Error' which is the product of the comparison which we want to minimize 


#if the error is smaller than the last best one, it replaces it. If not nothing changes 

if(error<as.numeric(bestvectors[1,3+1])|is.na(bestvectors[1,3+1])){ 
      bestvectors[1,]<-c(colnames(NIR)[i],colnames(NIR)[j],colnames(NIR)[k],as.numeric(error)) 
      bestvectors[,3+1]<-as.numeric(bestvectors[,3+1]) 
     } 
     } 
    } 
+0

Возможно, простейшее перечисление комбо 1140, а затем параллельное выполнение, а не работа с несколькими вложенными циклами. (Я не использовал 'foreach' и поэтому не получил полного ответа.) – Frank

+1

Пример, который я использую, является простым. На самом деле я ищу лучшие 5 векторов из 150, которые в конечном итоге составляют 591 600 030 комбинаций. Я не думаю, что перечисление всех комбо было бы практичным. – Jones

+3

Возможно, это больше 'stats.stackexchange.com', чем связанное с этим программирование R. Существуют методы борьбы с комбинаторным взрывом, такие как поэтапный выбор –

ответ

2

Общие рекомендации по использованию foreach:

  1. Используйте foreach(i=1:numcols) %dopar% { ... }, если вы хотите, чтобы ваш код для запуска на нескольких ядрах. Декоратор %do% несовершенно имитирует параллелизм, но работает на одном ядре.

  2. Процессы, порожденные %dopar%, не могут связываться друг с другом во время работы цикла. Итак, настройте свой код для вывода объекта R, например data.frame или vector, затем выполните сравнение потом. В вашем случае логика в строке if(error<as.numeric ... должна выполняться последовательно (не параллельно) после основного цикла foreach.

  3. Поведение вложенных цепей %dopar% противоречит операционным системам и неясно, как он порождает процессы по ядрам. Для обеспечения максимальной производительности и переносимости используйте одиночный цикл foreach в самом удаленном цикле, а затем в нем ванильные петли for.

+0

Спасибо! В конце концов я смог создать три вложенных цикла foreach, а два внутренних - с помощью '% do%' decorator и внешнего с использованием '% dopar%'. Теперь моя проблема заключается в логическом выражении 'if (error Jones

+0

У вас будет лучшее время, используя параметр «.combine =», если ваши внутренние циклы используют 'for (...) {...}' вместо 'foreach (.. .)% делают% {...} '. –

+0

Кроме того, вам может потребоваться распараллелить этот процесс, чтобы найти минимальную ошибку таким же образом. Если ваше учреждение имеет доступ к распределенным вычислениям, изучите R-дистрибутив, который автоматически распараллеливает функции стиля приложения на кластерах. –