2017-01-12 81 views
1

我無法理解如何使代碼並行。我的願望是從20個矩陣中找出3個向量,對我的測量變量產生最接近的線性迴歸(這意味着總共有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

我使用的例子很簡單。實際上,我正在尋找150箇中最好的5個向量,其結果是591,600,030個組合。我不認爲列舉所有的組合將是實際的。 – Jones

+3

也許它比'stats.stackexchange.com'更接近R編程。有一些方法可以處理組合式爆炸,如逐步選擇 –

回答

2

使用foreach一般建議:

  1. 使用foreach(i=1:numcols) %dopar% { ... },如果你想你的代碼在多內核上運行。 %do%修飾器不完美地模擬並行性,但在單個核心上運行。

  2. %dopar%產生的進程在循環運行時不能互相通信。因此,設置您的代碼以輸出R對象,如data.framevector,然後再進行比較。在你的情況下,if(error<as.numeric ...行中的邏輯應該在主循環之後順序執行(不是並行)。

  3. 嵌套%dopar%循環的行爲在不同操作系統中不一致,並且不清楚它是如何產生跨內核的進程的。爲了獲得最佳性能和便攜性,請在最外面的循環中使用一個單獨的foreach循環,然後在其中使用vanilla for循環。

+0

謝謝!我最終創建了3個嵌套的'foreach'循環,其中兩個使用'%do%'裝飾器,而另外兩個使用'%dopar%'。現在我的問題是邏輯陳述「if(error Jones

+0

如果你的內部循環使用for(...){...}而不是foreach(),你將會有更好的時間使用「.combine =」參數。 。)%做到%{...}'。 –

+0

此外,您可能想要以相同的方式並行化查找最小錯誤的過程。如果您的機構可以訪問分佈式計算,請查看R分佈,以便在集羣上自動並行化應用樣式函數。 –