본문 바로가기

[Rcpp] Rcpp에서 R함수 사용하기 (Optimize 함수 예시)

R Programming/Rcpp by Mandarim_ 2023. 9. 17.

(현재 코드는 RcppArmadillo & Rcpp 을 사용하였다.)

 

Rcpp은 R의 계산속도 향상을 위해  사용하지만, C++ 내부에 당연히 R의 패키지들은 다 구현되어 있지 않다...

 

R을 사용하다 속도 문제로 R코드를 C++로 수정하는 일이 종종 생기는데,

이 때 기존의 R에서 사용하던 함수를 직접 구현해야 하나 싶은 상황이 된다.

 

기존의 R 코드를 C++로 구현하는 건 매우 어려운 일인데,

 

R과 달리, C++은 Vector 단위의 객체끼리의 Row-wise 계산을 지원해주지 않아서 for()를 사용해 모든 element를 불러와서 계산한 후에 다시 그 값을 vector로 만들어야 한다.

결론적으로 내가 대가님이 몇 십년씩 조금씩 수정하여 만들어낸 몇몇 패키지 함수보다 더 안정적이고 효율적으로 짧은 시간에 구현해낼 가능성은 매우 낮다.

 

그러니 고생하지 말고, 어려운 함수는 불러와서 쓰자!!

 

Huber() 예시, 아래 링크의 코드를 참고해서 R의 Optimize()를 C++로 불러 왔다.

https://statkim.github.io/rcpp-tutorial/rcpp-use-r-function.html

 

Chapter 11 R 함수 사용하기 | Rcpp과 RcppEigen 튜토리얼

C++로 R 연산속도 높이기

statkim.github.io

 

Rcpp::Environment 로 환경 설정이 가능하며, Rcpp:Function 객체로 해당 패키지의 함수를 불러올 수 있다.

 

Optimize()의 경우,

기존 Optimize에서 사용하는 옵션 (Objective Function, Interval 등)과 Objective Function (코드에서 obj_fun_rcpp 함수) 에 사용되는 옵션 (b_Time, b_Delta, b_Z1, b_Z2, b_I)을 함께 사용해야 하는데,

 

(매우 중요) C++의 경우, 옵션 순서를 잘못 넣어주면 제대로 계산이 안되므로 주의하자.

제대로 짠 것 같은데, 계산이 이상하다?

R에 익숙해져서 옵션 순서를 제대로 확인하지 않고 짰을 가능성이 매우 높다!!

 

옵션 순서는 optimze 옵션 먼저 다 쓰고, 뒤에 obj_func_rcpp에 정의된 옵션 순서대로 작성한다.

<코드 예시>

// [[Rcpp::export]]
List optim_rcpp(arma::vec& b_Time, arma::vec& b_Delta,
                arma::vec& b_Z1, arma::vec& b_Z2, arma::vec& b_I){
  arma::vec bound = {-5, 5};
  
  // Extract R's optimize function
  Rcpp::Environment stats("package:stats");
  Rcpp::Function optimize_r = stats["optimize"];
  
  List opt_results = optimize_r(Rcpp::_["f"] = Rcpp::InternalFunction(&obj_fun_rcpp),
                                Rcpp::_["interval"] = bound,
                                Rcpp::_["b_Time"] = b_Time,
                                Rcpp::_["b_Delta"] = b_Delta,
                                Rcpp::_["b_Z1"] = b_Z1,
                                Rcpp::_["b_Z2"] = b_Z2,
                                Rcpp::_["b_I"] = b_I);
  
  return opt_results;
}
반응형