이번 포스팅에서는 Exponential r.v. 의 생성 방법에 대해 설명한다.

 

Exponential r.v. 의 pdf 는 다음과 같다.

 

 

위 pdf 를 적분하면 cdf 를 구할 수가 있고, cdf 는 다음과 같다.

  

 

Exponential r.v. 은 위 CDF 수식의 inverse 를 통해 구할 수 있으며 rand() 함수를 이용하여 다음과 같이 생성 할 수 있다.  

 

위 exponential generation 함수를 이용하여 exponential r.v. 을 생성해 보자.

 

아래 코드는 λ = 1 인 경우의 exponential r.v. 을 생성하고 그에 대한 pdf 및 cdf 그래프를 그리는 코드이다.

 

 

위 코드에 따른 pdf 및 cdf 는 다음과 같다.

 

 

 

 

pdf, cdf code 에 대한 내용은 다음 글을 참조하기 바란다.

 

2011/03/23 - [MATLAB] - MATLAB PDF, CDF, CCDF 
 

Exponential r.v. 의 평균 및 분산은 다음 식과 같다.

 

,    

 

λ = 1 인 경우 평균 및 분산은 1 이다.

 

시뮬레이션을 통해 알아본 λ = 1 인 경우의 평균 및 분산은 다음과 같다.

 

 

실험 결과가 이론 값과 근사적으로 일치함을 확인 할 수 있다.


  1. 지나가던 행인 2012.11.10 23:45

    저기 근데 exponential인데 왜 log를 썼죠;;;ㅠ
    exponential 쓰니까 안나오고
    log 쓰니까 나오긴 하는데 이유를 모르겠어요ㅠ

    • 남성 2012.11.11 00:34 신고

      MATLAB 의 log() 함수는 자연로그 입니다.
      random variable 을 생성하는건 CDF 의 역 함수를 이용하니깐
      위 exponential r.v. CDF 의 인버스를 구하는걸 생각해 보면 ln() 을 쓰는게 이해가 되실겁니다.

  2. 2012.11.11 17:11

    비밀댓글입니다

    • 남성 2012.11.11 19:26 신고

      위 포스팅에서 CDF 수식의 inverse 를 구한다고 생각하면 exp() 함수가 없어지고. ln() 함수가 들어가겠죠~
      CDF 란 0~1 사이의 값이고 MATLAB 의 rand() 함수는 0~1 사이의 random 값이 나온다는것을 생각해 보면 이해가 되실것 같네요.

  3. 2012.11.11 17:12

    비밀댓글입니다

  4. 남성님 2016.01.06 14:27

    inverse여서 log를 이용한것까진 이해를 했는데요..
    왜 rand 앞에 1/lambda 는 곱해져 있지 않은걸까요 ㅠ_ㅠ
    수식상으로는 원래 있는데 말이죠..

    • 남성 2016.01.06 18:22 신고

      위에 코드 캡쳐화면 보면 1/lambda 곱해져 있는데요.... ^^;

  5. 남성님 2016.01.12 19:27

    그 log밖이랑 안 둘다 1/lambda를 곱해야하는거 아닌가요?
    exponential r.v. pdf의 경우 lambda*exp(-lambda*x) 로 알고있어서.. ㅠㅠ
    그래서 그걸 inverse 취하면 1/lambda*log(1/lambda(rand(~~)) 이렇게 되야할 것만 같은데 ㅠㅠ
    그렇게 하면 또 원하는 결과를 얻을수 가없더라구요 ㅠㅠ 제가 잘못생각하고 있는걸까요?ㅠㅠ

    • 남성 2016.01.12 20:38 신고

      PDF 의 inverse 가 아니라 CDF 의 inverse 입니다. rand() 함수는 0~1 의 값을 출력하는 uniform random variable 이기 때문에 CDF 값이 0~1사이 값이므로 이를 이용해서 Random variable 을 generation 하는 겁니다.

      위에 포스팅에서는 코드는 맞게 했는데 제가 CDF 수식을 잘못 적었네요 오해의 소지가 있었네요 ^^; 수정 했습니다.

      아래 위키 피디아를 보시면
      https://en.wikipedia.org/wiki/Exponential_distribution

      Generating exponential variates 라는 부분이 있는데 그 부분을 보시면 좀더 쉽게 이해 하실 겁니다.






  6. 남성님 2016.01.13 15:47

    감사합니다.
    덕분에 확실하게 알아가게되었어요^.^
    자주 방문하겠습니다!

  7. 감사합니다 2020.04.12 02:44

    포스팅 감사합니다 너무 유익해요!!

    -역함수를 구할 때 왜 ln이 아니라 밑 상관없이 log로 쓰는지 궁금합니다.
    -resolution과정은 왜 필요한지 궁금합니다.

    • 남성 2020.04.12 03:02 신고

      MATLAB 명령창에 help log 라고 하면 알겠지만 MATLAB log 함수는 자연로그를 의미하쥬~ 그러니까 ln = log 쥬~ MATLAB 에 ln 함수는 없쥬~

      resolution 과정 즉 정규화 과정은 PDF의 면적은 1 이기 때문에 PDF 의 전체 적분값이 1이 되게 하려구 한 거쥬~

      방금 술 먹고 백종원 레시피를 봤더니 ㅡㅡ;

C/C++ 프로그래밍에 대한 기존의 제 선입견은 코드량이 많다 입니다.

실행 속도가 다른 언어들 보다 훨씬 빠르지만~

하나하나 짜려면 그 라인 수가 너무 많아서 생산성이 그리 좋지 못하다는 선입견이죠.

그런데 요즘 C++ 의 변화를 보고 있으면 그 변화가 눈부시다는 생각이 들더군요.

C++ 코딩을 하면서 종종 참조하는 사이트인데~ 들어가면 각종 라이브러리나 함수에 대한 정의 및 예제, C++ Tutorial, C++ 역사 등등 C++ 과 관련한 정말 다양한 정보를 얻을 수 있는 사이트 입니다.

 

http://www.cplusplus.com

 

그런데 위 사이트에서 돌아다니다 보면 C++11 이라는 것들이 눈에 띄더군요.

뭔가 해서 보니 2011 년 9월에 만들어진 C++ 표준이라서 C++11 이라고 한다네요.

아래 주소에는 Alex Allain 이라는분이 C++11 에 대해 소개한 내용입니다.

 

http://www.cprogramming.com/c++11/what-is-c++0x.html

 

auto 라는 대단히 편리한 키워드가 눈에 띄더군요. 또한 기존에 nested 형태로 STL 들을 정의 할 때 아래 코드의 빨간색 부분처럼 닫는 Angle Brackets 을 띄어 써야 했었는데 ~~ 아마도 right shift 와 구분이 잘 안돼서 그랬던 듯 ~

 

vector<vector<int> > vector_of_int_vectors;

 

C++11 에서는 이러한 불편함도 수정되서 아래 예처럼 그냥 붙여 쓸 수 있습니다.

 

vector<vector<int>> vector_of_int_vectors;

 

Python에서 보았던 Tuple 이나 Lambda Functions 등도 지원을 하더군요.

 

http://www.cprogramming.com/c++11/c++11-lambda-closures.html

 

C++ 의 다양한 변화에 탄복하다가 Numerics library 의 Pseudo-random number generation 이라는 부분에 눈길이 가더군요.

기존에 C/C++ 에서는 rand() 라는 uniform random number generator 만 제공을 해 줬었죠.


다른 분포 특성들은 이 rand() 함수를 이용해서 알고리즘을 다 이해한 후 하나 하나 작성해야 했습니다.

아래 포스팅에 썼던 것처럼 말이죠. 


2012/01/02 - [컴퓨터일반] - Gaussian Random Variable generation C code


 

 

그런데 C++11 의 Pseudo-random number generation 이 생긴 이후로는 그럴 필요가 없어졌습니다.

 

http://www.cplusplus.com/reference/std/random/


 

위 주소를 보면 아래와 같이 다양한 분포 특성에 대한 생성 함수를 제공해 준다는 것을 알 수 있습니다.

 

우리가 흔히 정규분포라고 얘기하는 Normal(Gaussian) 분포에서부터~ Uniform discrete, Uniform real, Bernoulli, Binomial, Geometric, Negative binomial, Poisson, Exponential, Gamma, Weibull, Extreme Value, Lognormal, Chi-squared, Cauchy, Fisher F, Student T, Discrete, Piecewise constant, Piecewise linear 까지~~ 간단하게 생성 할 수 있습니다.

 

무지하게 편리하겠죠~

 

C++11 너무 써보고 싶어서 간단하게 Gaussian generation 을 해 봤습니다. 아래 주소의 예제 참조 했구요~ 약간 수정했습니다.

 

http://www.cplusplus.com/reference/std/random/normal_distribution/

 

C++11 은 최신의 표준이니 만큼 최신의 컴파일러를 설치해야 되더군요. 저는 GCC 4.7.1 버전을 설치 했습니다. 아래 주소에서 다운로드 받았구요~

 

http://nuwen.net/mingw.html

 

Stephan T. Lavavej 라는 분의 개인 홈피인데~ 마이크로 소프트에서 일한다는 군요 ㅋㅋㅋ Thank you~~~

 

어쨌든 GCC 최신 버전을 설치하고 평균이 5 이고 표준 편차가 4 인 Gaussian random number 를 생성해 봤습니다.

 

코드는 다음과 같습니다.

 

#include <iostream>

#include <iomanip>

#include <string>

#include <map>

#include <random>

#include <cmath>

 

using namespace std;

 

int main()

{

    default_random_engine generator;            // generator 생성

    normal_distribution<double> distribution(5.0,4.0);

 

    map<int, int> hist;            // hostogram 을 그리기 위한 버퍼

    for(int n=0; n<5000000; ++n) {

        ++hist[std::round(distribution(generator))];            // histogram buffering

    }

 

    for(auto p : hist) {                        // * 로 나타내기

        std::cout << std::fixed << std::setprecision(1) << std::setw(2)

            << p.first << ' ' << std::string(p.second/25000, '*') << '\n';

    }

    getchar();                // 결과 창이 없어지지 않게 하기 위함

    return 0;

}

 

위 코드를 돌려 보면~ 아래와 같이 나오더군요~ 많이 본~~ 정규 분포를 세워 놓은 모양이죠? 위에 보시는 바와 같이 코드량이 정말 짧더군요.




 

C++11 강추입니다.


+ Recent posts