2016-02-03 5 views
0

Я пытаюсь запустить сценарии моделирования, которые, в свою очередь, должны предоставить мне лучший сценарий для заданной даты, обратно протестированный на пару месяцев. Вход для конкретного сценария имеет 4 входных переменных, причем каждая из переменных может находиться в 5 состояниях (625 перестановок). Поток модели выглядит следующим образом:Параллельная обработка для нескольких вложенных циклов

  1. Simulate 625 сценарии, чтобы получить каждый из своей прибыли
  2. ранга каждые из сценариев в зависимости от их прибыли
  3. Повторите процесс через расширяющееся окно 1 дня для последние 2 месяца, начинающиеся 1 декабря 2015 года, - создание временных рядов рангов по каждому из 625 сценариев.

Несчастливый результат для этого - 5 вложенных для циклов, которые могут занять очень много времени. Я взглянул на пакет foreach, но я обеспокоен тем, как объединение результатов будет работать в моем сценарии.

текущий код, который я использую работает следующим образом, сначала я создаю возможные состояния каждого из входов вместе с окном

a<-seq(as.Date("2015-12-01", "%Y-%m-%d"),as.Date(Sys.Date()-1, "%Y-%m-%d"),by="day") 
#input variables 
b<-seq(1,5,1) 
c<-seq(1,5,1) 
d<-seq(1,5,1) 
e<-seq(1,5,1) 

set.seed(3142) 

tot_results<-NULL 

Следующая вложенная для петель перейти к пробегают моделирования для меня ,

for(i in 1:length(a)) 
{ 
cat(paste0("\n","Current estimation date: ", a[i]),";itteration:",i," \n") 
#subset data for backtesting 
dataset_calc<-dataset[which(dataset$Date<=a[i]),] 
p=1 
results<-data.frame(rep(NA,625)) 
    for(j in 1:length(b)) 
    { 
     for(k in 1:length(c)) 
     { 
      for(l in 1:length(d)) 
      { 
       for(m in 1:length(e)) 
       { 
       if(i==1) 
       { 
        #create a unique ID to merge onto later 
        unique_ID<-paste0(replicate(1, paste(sample(LETTERS, 5, replace=TRUE), collapse="")),round(runif(n=1,min=1,max=1000000))) 
       } 
       #Run profit calculation 
       post_sim_results<-profit_calc(dataset_calc, param1=e[m],param2=d[l],param3=c[k],param4=b[j]) 
       #Exctract the final profit amount 
       profit<-round(post_sim_results[nrow(post_sim_results),],2) 

       results[p,]<-data.frame(unique_ID,profit) 
       p=p+1 
       } 
      } 
     } 
    } 
    #extract the ranks for all scenarios 
    rank<-rank(results$profit) 

    #bind the ranks for the expanding window 
    if(i==1) 
     { 
      tot_results<-data.frame(ID=results[,1],rank) 
     }else{ 
      tot_results<-cbind(tot_results,rank) 
     } 
    suppressMessages(gc()) 
} 

Моя самая большая проблема заключается в связывании результатов, учитывая, что действия внешнего цикла находятся в зависимости от мощности внутренних петель.

Любой совет о том, как продолжить, будет очень признателен.

+2

Из вашего кода кажется, что вы можете просто векторизовать все это? С 'expand.grid (a, b, c, d, e)' в качестве вашего ввода. – Laterow

+0

Большое вам спасибо за полезный комментарий. Мой фон, к сожалению, не основан на программировании, поэтому, хотя я понимаю концепцию «векторизации» проблемы, я ранее не реализовал эти структуры. Знаете ли вы о хорошем источнике, возможно, где я могу взглянуть на некоторые примеры? Или, может быть, если бы вы были настолько любезны, чтобы предоставить образец слова вложенной петли с функциями 3 'for', которые я мог бы просто создать из –

ответ

1

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

В настоящее время вы используете for -loops (5, если быть точным), чтобы создать каждую комбинацию значений, а затем запустите значения один за другим через profit_calc (функция, которая не указана). В идеальном случае вы просто возьмете все возможные комбинации за один раз и пропустите их через profit_calc за одну операцию.

- Обоснование -

a <- 1:10 
b <- 1:10 
d <- rep(NA,10) 
for (i in seq(a)) d[i] <- a[i] * b[i] 
d 

# [1] 1 4 9 16 25 36 49 64 81 100 

С * также работает над векторами, мы можем переписать это:

a <- 1:10 
b <- 1:10 
d <- a*b 
d 

# [1] 1 4 9 16 25 36 49 64 81 100 

Хотя это может спасти нас только одна строка кода, то фактически уменьшает проблему с 10 шагов до 1 шага.

- Применение -

Так как это применимо к вашему коду? Ну, учитывая, что мы можем векторизовать profit_calc, вы можете в основном генерировать кадр данных, где каждая строка является любой возможной комбинацией ваших параметров. Мы можем сделать это с expand.grid:

foo <- expand.grid(b,c,d,e) 
head(foo) 

# Var1 Var2 Var3 Var4 
# 1 1 1 1 1 
# 2 2 1 1 1 
# 3 3 1 1 1 
# 4 4 1 1 1 
# 5 5 1 1 1 
# 6 1 2 1 1 

Допустим, мы имеем формулу ... (a - b)/(c + d) ...Тогда он будет работать как:

bar <- (foo[,1] - foo[,2]) * (foo[,3] + foo[,4]) 
head(bar) 

# [1] 0 2 4 6 8 -2 

Так в основном, пытается найти способ заменить for -loops с векторизованными вариантами. Если вы не можете что-то векторизовать, попробуйте вместо этого взглянуть на apply, поскольку это может также сэкономить вам некоторое время в большинстве случаев. Если ваш код работает слишком медленно, в идеале вы сначала увидите, можете ли вы написать более эффективный скрипт. Кроме того, вас может заинтересовать библиотека microbenchmark, или ?system.time.

+0

, спасибо за это краткое и интуитивное объяснение! Действительно ценю это –

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