2017-09-26 2 views
0

내가하려고하는 일반적인 버전은 몇 가지 변수를 조작하여 시뮬레이션 결과가 어떻게 영향을 미치는지 시뮬레이션 연구를 수행하는 것입니다. R과 속도 문제가 있습니다. 최신 시뮬레이션은 몇 번의 반복 (실험 당 10 회)으로 작업했습니다. 그러나 대규모 버전 (실험 당 10k) 버전으로 이동하면 시뮬레이션은 14 시간 동안 실행되었습니다 (아직 실행 중입니다).코드 최적화를 사용하여 R에서 시뮬레이션 속도 향상

다음은 내가 실행중인 코드입니다 (주석 포함). R과 신인이기 때문에 효율적인 시뮬레이션을 위해 고심하고 있습니다. 이 코드를 최적화하고 향후 시뮬레이션 연구에 이러한 코멘트를 사용하기 위해 여기에 제공된 의견 및 제안을 통해 도움을 얻으십시오.

이 코드의 기능에 대해 몇 가지 말씀 드리겠습니다. 효과 크기와 표본 크기의 두 변수를 조작하고 있습니다. 각 조합은 10k 회 실행됩니다 (조건 당 10k 실험). 결과 (결과)를 저장하기 위해 데이터 프레임을 초기화합니다. 효과 크기, 샘플 크기 및 반복 (10k)의 세 변수를 반복합니다.

루프 내에서 4 개의 NULL 구성 요소 (p.test, p.rep, d.test 및 d.rep)를 초기화합니다. 전자의 두 값은 초기 t-test의 p 값과 복제의 p 값 (유사한 조건에서 복제 됨)을 캡처합니다. 후자의 두 개는 효과 크기를 계산합니다 (Cohen 's d).

제어 조건 (DVcontrol)에 대한 표준 정규에서 임의의 데이터를 생성하고 실험 조건 (DVexperiment)의 평균으로 내 효과 크기를 사용합니다. 나는 값들 사이의 차이를 취하고 그 결과를 R의 t- 테스트 함수로 던진다 (paired-samples t-test). Trials라고하는 목록에 결과를 저장하고이를 결과 데이터 프레임에 연결합니다. 이 과정은 완료 될 때까지 10k 번 반복됩니다. 여러분의 의견과 제안에 미리

# Set Simulation Parameters 
## Effect Sizes (ES is equal to mean difference when SD equals Variance equals 1) 
effect_size_range <- seq(0, 2, .1) ## ES 
## Sample Sizes 
sample_size_range <- seq(10, 1000, 10) ## SS 
## Iterations for each ES-SS Combination 
iter <- 10000 

# Initialize the Vector of Results 
Results <- data.frame() 

# Set Random Seed 
set.seed(12) 

# Loop over the Different ESs 
for(ES in effect_size_range) { 

    # Loop over the Different Sample Sizes 
    for(SS in sample_size_range) { 

    # Create p-value Vectors 
    p.test <- NULL 
    p.rep <- NULL 
    d.test <- NULL 
    d.rep <- NULL 

    # Loop over the iterations 
    for(i in 1:iter) { 

     # Generate Test Data 
     DVcontrol <- rnorm(SS, mean=0, sd=1) 
     DVexperiment <- rnorm(SS, mean=ES, sd=1) 
     DVdiff <- DVexperiment - DVcontrol 
     p.test[i] <- t.test(DVdiff, alternative="greater")$p.value 
     d.test[i] <- mean(DVdiff)/sd(DVdiff) 

     # Generate Replication Data 
     DVcontrol <- rnorm(iter, mean=0, sd=1) 
     DVexperiment <- rnorm(iter, mean=ES, sd=1) 
     DVdiff <- DVexperiment - DVcontrol 
     p.rep[i] <- t.test(DVdiff, alternative="greater")$p.value 
     d.rep[i] <- mean(DVdiff)/sd(DVdiff) 
    } 

    # Results 
    Trial <- list(ES=ES, SS=SS, 
        d.test=mean(d.test), d.rep=mean(d.rep), 
        p.test=mean(p.test), p.rep=mean(p.rep), 
        r=cor(p.test, p.rep, method="kendall"), 
        r.log=cor(log2(p.test)*(-1), log2(p.rep)*(-1), method= "kendall")) 
    Results <- rbind(Results, Trial) 
    } 
} 

감사합니다, 조쉬

+2

이것은 여기보다는 [codereview.se]에 속한 것처럼 보입니다. –

+2

@JohnColeman 두 사이트 모두 주제에 관한 것 같습니다. 코드 검토 요청뿐만 아니라 특정 질문 ("이 코드의 속도를 높이려면 어떻게합니까? 하루가 걸릴 수 있습니다)"입니다. – Zeta

+0

이 게시물을 제거하고 필요한 경우 코드 검토로 옮길 수 있습니다. – Josh

답변

2

최적화에 대한 일반적인 접근 방식에 다음 인터프리터에서 대부분의 시간을 보낸다 코드의 어떤 부분을 확인하기 위해 profiler을 실행하는 것입니다 그 부분을 최적화하십시오. 코드가 test.R이라는 파일에 있다고 가정 해 보겠습니다. R에서는 다음 명령 시퀀스를 실행하여 프로파일 링 할 수 있습니다 : (.이 명령이 R 세션의 디렉토리에있는 파일 Rprof.out을 생성합니다)

Rprof()    ## Start the profiler 
source("test.R") ## Run the code 
Rprof(NULL)  ## Stop the profiler 
summaryRprof()  ## Display the results 

을 우리가 프로파일 러를 실행하는 경우 코드에 (iter <- 10보다는 iter <- 10000로), 우리는 다음과 같은 프로필 얻을 : 여기에서

# $by.self 
#       self.time self.pct total.time total.pct 
# "rnorm"      1.56 24.53  1.56  24.53 
# "t.test.default"    0.66 10.38  2.74  43.08 
# "stopifnot"     0.32  5.03  0.86  13.52 
# "rbind"      0.32  5.03  0.52  8.18 
# "pmatch"      0.30  4.72  0.34  5.35 
# "mean"      0.26  4.09  0.42  6.60 
# "var"      0.24  3.77  1.38  21.70 

을, 우리는 rnormt.test이 가장 비싼 작업 (것을 관찰 이것들이 당신의 내면의 루프에 있기 때문에 놀랄만 한 것은 아닐 것입니다).

  1. 최적화 기능, 및/또는
  2. 는 함수가 호출 횟수를 최적화 : 고가의 함수 호출은 위치를 알아 낸 후

    는 실제 최적화는 두 단계로 구성되어 있습니다.t.testrnorm 이후

가 내장되어 R 기능, 1 단계에 대한 유일한 옵션은 위의 정규 분포 및/또는 여러 t 테스트를 실행 샘플링 속도 구현이있을 수 있습니다 다른 패키지를 보는 것입니다. 2 단계는 실제로 동일한 것을 여러 번 다시 계산하지 않는 방식으로 코드를 재구성하는 것입니다.

# Generate Test Data 
DVcontrol <- rnorm(SS, mean=0, sd=1) 
DVexperiment <- rnorm(SS, mean=ES, sd=1) 

가 루프 밖에서이 이동하는 것은 의미가 있는가, 또는 당신은 정말 i의 각각 다른 값에 대한 테스트 데이터의 새로운 샘플이 필요합니까 예를 들어, 다음 코드 줄은 i에 의존하지 않는 ?

+0

귀하의 의견을 보내 주셔서 감사합니다! 귀하의 질문에 답하기 위해 필자는 실험의 조건을 여러 번 (이 경우 10k) 반복해야하기 때문에 루프 외부에서 코드를 움직일 수는 없습니다. 그렇지 않으면 훌륭한 해결책이 될 것입니다. – Josh

+1

Gotcha. 하나의 대안은 루프 밖에서'rnorm' 호출을 이동시키는 것일 수 있지만, 한번에'SS * iter' 값을 샘플링하도록합니다 (즉, 단일 호출에서 모든 루프 반복의 모든 값). 루프 내에서 샘플의 적절한 부분에 코드를 액세스하게 할 수 있습니다. 'rnorm' 호출과 관련된 많은 오버 헤드가 있다면 코드 속도를 높여야합니다. –

+2

또 다른 생각 :'DVcontrol'과'DVexperiment'를 직접 사용하지 마십시오. 그러나 두 정규 분포의 차이도 정상입니다 : http://mathworld.wolfram.com/NormalDifferenceDistribution.html. 그렇다면 'DVdiff'값을 직접 생성하지 말고'rnorm' 호출의 수를 50 % 줄이십시오. –

관련 문제