개요

(가상의 상황) 어느 날 다음의 요구사항이 들어온다.

(1) 과녁을 향해 화살을 쏘는데 정밀도(능력치)가 낮으면 골고루 쏘고, 정밀도가 높으면 한 곳에 더 집중해서 쏜다. (2). 근데 정밀도가 높아도 오발이 약간은 있어야함. 물론 정밀도가 높을 수록 오발은 줄어들것.

이것에 대한 구현 방법은 무척 많다. 가장 좋은 방법이란 없다. 여기서는 그 중에, (물론 내가 생각하기에) 가장 엘레강트하고 뷰티풀한 방식인 수학의 확률을 이용한 방법을 소개한다.

1번의 조건만 있다면, 그리고 쉽게 구현을 하고자 한다면 다음과 같이 표현되도록 그 범위만 지정하면 된다.

polar-const polar-const-small
<그림 1> 정밀도가 낮을때, 높을 때

하지만 2번의 조건이 있을 경우, 또는 없더라도 좀 더 창의성을 발휘하면 다음과 같이 할 수도 있다. 여기서 빨간색은 화살이 많이 쏴진 지역을 뜻한다.

polar-const polar-x^2
<그림 2> 정밀도가 낮을때, 높을 때

이 글에서 다룰 내용은

  1. 위와 같은 분포 그래프를 만들고,
  2. 점을 찍을 때(화살을 쏠 때), 원하는 분포가 나오도록

하는 것이다. 보통은 일반적으로 일정한 분포로 값을 내주는 랜덤 값을 이용하기 때문에, 일정한 분포의 값을 원하는 분포로 변환하는 것이 가장 핵심이라고 볼 수 있다.

확률 밀도 함수(Probability Density Function, PDF) 만들기

원래는 원 모양의 2차원 과녁을 생각해야하지만, 편의상 그냥 1차원으로 생각해서 거리만 생각한다.

linear-const linear-4x^3
<그림 3> 세로축은 랜덤. 가로축이 과녁과의 거리의 역(오른쪽에 맞을 경우 더 정확히 쏜 것으로 간주). 왼쪽 그림은 점의 분포가 동일한데, 오른쪽 그림에는 x=1 부분에 더 많은 점이 찍혀 있다.

위의 그림의 확률 분포를 그래프로 그리면 아래와 같다.

graph-y=1 graph-y=4x^3
<그림 4>x축은 정확도. y축은 확률 밀도(probability density)

x축이 1인 지점은 화살을 정확하게 명중 시키는 것을 뜻하고, 0인 지점은 가장 빗나가게 쏜 것을 뜻한다. 이때 y축이 확률 밀도 함수(PDF, probability density function)다.

일단 확률 밀도가 생소할 수도 있는데, 일단은 틀리지만 쉬운 의미로는 그냥 그 지점의 확률이라 생각해도 된다.

위의 <그림 4.b>에서 PDF인 P는 다음의 형태를 취한다.

  • LaTeX equation

여기서 x=1일 경우 확률 밀도가 4이고, x=0일 경우 확률 밀도가 0이라는 말인데, 확률 밀도는 확률과 비슷하지만 조금 달라서 1을 넘을 수가 있다[1].

여기서 중요한 조건이 있다. x의 범위는 임의로 0부터 1까지로 잡았는데, 이 구간의 PDF 값을 적분하면 1이 되어야 한다(화살을 쏠 때 불발이 없다는 가정).

  • LaTeX equation

<그림 4.b>에 해당하는 이 함수를 구현을 하면(어떻게 구현하는지는 밑에 설명), <그림 3.b> 처럼된다.

정밀도와 연결하기

LaTeX equation라는 곡선은 LaTeX equation 함수에서 b를 3으로 지정했을 때 a가 4가 됨을 구해서 얻은 곡선이다. 즉, LaTeX equation 함수를 적분하면 1이 되는 점을 이용하면, a = b+1 의 관계가 성립됨을 알 수 있다. 결국 LaTeX equation 형식으로 그래프를 만들 수 있다. 여기서는 편의상 계속 b를 3으로 두고 진행한다(하지만 사실 상수로 바꾸지 않고 b로 둬도 별로 어렵지는 않다).

이걸 정밀도 s이라는 변수와 함께 사용해보자. s이 0일 경우 화살을 워낙 못쏴서 고르게 쏘도록 할때(<그림 3.a>, 사실 이렇게 쏘는 것도 능력이긴하다.)의 PDF는 LaTeX equation이라 정하고, s=1일 경우는 방금 만든 가파른 곡선인 LaTeX equation 를 사용한다.

방금의 두 PDF, LaTeX equation, LaTeX equation 를 s를 이용해서 선형보간을 시켜보자. 그러면 최종적으로 LaTeX equation 이 되는데, 여기서 한번 더 이 새로운 PDF도 적분 했을 때 1이 되는지 확인해보면 무리 없이 1이 된다.

여기까지의 과정을 그래프로 그려보자. LaTeX equationLaTeX equation는 둘다 2차원 그래프지만, 여기에 s을 더하면 3차원 그래프가 된다.

(1-s)+s4x^3
<그림 5>LaTeX equation

s=0일 때의 단면 그래프는 <그림 4.a>와 같고 s=1일 때의 그래프는 <그림 4.b>와 같다. 0.5 쯤에 있는 애매한 그래프도 바로 얻을 수 있는 장점이 있다[2].

누적 분포 함수(Cumulative Distribution Function, CDF) 만들기

자, PDF 함수를 만들고 나면 끝인 것 같지만, 큰 장벽이 남아 있다.

PDF는 확률 분포다. 확률 분포만으로는 제대로 사용할 수 없다. 어떤식으로 사용해야하냐면, 우리가 임의 랜덤 값을 주고 함수에 넣으면 짠 하고 원하는 값이 나와야 하는데, 그 원하는 값의 분포가 바로 PDF여야 한다. 좀 더 구체적으로 말하자면 실제 PDF와 우리가 사용해야할 함수는 사이에 CDF라는 함수가 존재하고, 우리가 필요로하는 함수는 CDF의 역함수다.

CDF 함수는 누적 분포 함수(Cumulative Distribution Function)를 뜻하며, PDF 함수로부터 다음과 같이 정의 된다.

  • LaTeX equation

즉, C(x) 값은 x가 0부터 x까지인 구간(전구간)의 PDF 함수를 적분한 것이다. 처음 전제조건으로 PDF를 적분하면 1로 하기로 했기 때문에 결국 (적어도 여기서는) C(1)는 항상 1이다.

어쨌건 한번 CDF를 구해보자.

  • LaTeX equation
  • LaTeX equation

이걸 다시 그래프로 그리면 다음과 같다. s가 어떤 값이던지 C(0)는 0이고, C(1)는 1인 것이 특징이다.

(1-s)x + sx^4
<그림 6>CDF에서는 x가 0에서 1로 올라갈때 CDF값(y축)도 같이 올라가는 것이 특징. s값에 관계 없이 항상 C(0)=0, C(1)=1이다.

드디어 막다른 골목을 마주하게 된다. 최종적으로 CDF의 역함수를 구해야하는데, 결론부터 말하자면 이 C(x) = (1-s)x + sx^4 는 역함수가 존재하지 않아서, 이걸 그대로 사용할 수가 없다.

왜 CDF의 역함수가 필요한지는 밑에서 보고, 아무튼 일단 이걸 우회하기 해보자. 방금은 LaTeX equationLaTeX equation에서 LaTeX equation를 만들고 LaTeX equation를 만들었는데, P(x)를 합치지 말고, C(x)의 역함수를 만들고 합쳐보자.

  • LaTeX equation
  • LaTeX equation
  • LaTeX equation
  • LaTeX equation
  • LaTeX equation

최종적으로 LaTeX equation이므로 LaTeX equation에서 y값이 우리가 전달해줄 랜덤 값이 되고 y값으로부터 원하는 x값을 얻게 된다.

CDF의 역함수

왜 역함수가 필요한지를 살펴보자. C(X)의 역함수부터 보자. PDF는 결코 음수는 될 수 없기 때문에 CDF에서 x가 0부터 1로 점차 늘어갈 수록 y값은 절대 줄어들지 않고 점점 늘어만 간다.

x^4 with line
<그림 7>

역함수라 함은 y축과 x축이 바뀐 형태를 뜻한다. 이 그래프에서 축 자체를 바꾸지 않고, y축에서 일정한 간격으로 y값을 선택한다고 해보자(빨간선), 그러면 그에 해당하는 x축의 x값이 나오는데, 이 x값이 바로, PDF에 따라 분포된다. 즉, 파란선을 보면 x=1에 가까운 곳에 더 집중되어 분포가 되는 것을 알 수 있다(y축의 빨간선이 일정한 가격인 것이 중요).

결국 C(x) 역함수에 우리가 (0과 1사이에) 고르게 분포된 랜덤 값을 하나 전달하면, 필요한 값(이 경우 정확도 x)이 나온다. 이것은, 우리가 어떤 함수의 분포인 PDF를 정의하면 일정한 분포를 가지는 랜덤 값들의 집합을 통해 원하는 PDF 형태로 분포되어 있는 값들의 집합을 얻을 수 있다는 것이 된다.

후... 길게 왔다. 결국엔 수식 LaTeX equation 한 줄이 나오고, 자바스크립트 한 줄 코드인

return (1-s)*y + s * Math.pow( y, 1/(b+1) ); // b는 편의상 3

요걸 얻어내기 위해 여기까지 왔다. 랜덤값 y를 전달해주면, x값이 리턴된다. 그 값을 쓰면 되고, s값 조절에 따라 분포가 달라지는 것을 확인할 수 있다.

s값의 변화에 따른 분포를 확인하기 위해 자바스크립트로 웹 시뮬레이터(?)를 만들어봤다.

클릭하세요.

  • 이 자바스크립트 코드는 크롬 15, 사파리 5.1.1에서 테스트 되었음.
  • 오페라에서는 dat.GUI 라이브러리 문제로 실패했음. IE는 테스트하지 않음.
  • dat.gui 라는 자바스크립트 GUI 라이브러리를 사용했음.
  • Acuracy는 이 글에서 말하는 s 변수.
  • FunctionType 을 Polar로 바꾸면 원형 과녁으로 바꿔볼 수 있음.

눈치 챈 사람도 있겠지만, 여기에 한 가지 함정이 있는데, LaTeX equation로는 안타깝게도 원하는 <그림 2>의 원형 과녁을 만드는데 사용할 수 없다. 그 이유는, 지금까지는 1차원적인 것들만 생각해서 x를 거리의 역으로 생각했는데, 이걸 그대로 사용해서는 원하는 분포를 얻을 수 없다. <그림 2>의 원형 과녁은 2차원의 극 좌표계로 표현해야하기 때문에 다시 다 계산해야한다[3]. 과정은 다소 복잡해서 과감히 생략하고, 결론적으로 함수는 다음과 같이 변형된다.

  • LaTeX equation
  • LaTeX equation
  • LaTeX equation
  • LaTeX equation
  • LaTeX equation
  • LaTeX equation

그리고,

  • LaTeX equation
  • LaTeX equation
  • LaTeX equation
  • LaTeX equation
  • LaTeX equation
  • LaTeX equation

여기서 LaTeX equation, LaTeX equation 같은 함수는 약간 꽁수를 통해 구했다[4]. 이 전반적인 과정은 숙제(-_-ㅋ?)로 남기도록 하겠다(극 좌표계와 데카르트 좌표계의 변환에 대해 덜 익숙한 사람들에게는 어려울 수 있다. 참고자료인 PBRT책을 참고할 것을 강력히 추천한다.).

위에 있는 웹 시뮬레이터에서 FunctionType을 Linear에서 Polar로 변경하면 원형 과녁을 볼 수 있다. 슬라이더 컨트롤에서 Ability는 s값을 의미하는 것으로 0과 1사이로 조절할 수 있다. s값이 1에 가까울 수록 특정 지점에 집중 되는 것을 확인하면 된다.

응용 & 결론

사실 나 같은 사람이야 이런 과정을 재밌어 하는 건데, 분명 그렇지 않은 사람들도 많고, 또 이 과정은 그렇게 본보기가 되기 좋은(사용하기 쉬운, 깔끔한) 과정은 아니다.

하지만 이렇게 한번 해두면

return (1-s)*y + s * Math.pow( y, 1/(b+1) );

혹은

return (1-s)*Math.sqrt( y ) + s * Math.pow( y, b );

같은 쉬운 코드가 나오고, 이 코드는 그때부터 이론적인 도출 없이 이것저것 (s값의 변화를 조절하거나 b값을 조절하는 방법 등) 커스터마이징 해볼 수 있다. 모든 것이 다 이론적으로 완벽한 수식으로 떨어질 순 없다. 하지만, 그렇다고 이론적인 도출 과정 없이 위의 함수를 만들어내는 것도 사실 쉽지 않다. 가장 좋은 방법은 이론의 명확함과, 현실적인 시도(다른 말로 삽질)가 부드럽게 어울려지는 것이라 생각한다.

참고문헌

  • Physically Based Rendering: from Theory to Implementation 2/E, Matt Pahrr, 2010
  • dat.gui: 자바스크립트 GUI 라이브러리
  • WolframAlpha: 2D/3D 그래프는 여기서 그렸음.


  1. 심지어 무한대가 될 수도 있다. 디락 델타 함수 참조. [본문으로]
  2. 이 때 1-s와 s를 사용하지 않고 예를 들어 1-s^2와 s^2를 사용할 수도 있다. 그러면 양 끝이 아닌 중간도 정밀도에 따른 변화 정도를 조절할 수 있다. [본문으로]
  3. 사실은 극 좌표계를 쓰지 않고 샘플을 걸러내는 방법으로 우회하면 가능하다. 리젝션 방법(Rejection method)이라고도 하는데, 사실 이 방법이 이어서 설명하는 방법보다 훨씬 깔끔하다(물론 장단점이 있다). [본문으로]
  4. 구했다기보다는 정확하게는 사용하기 쉬운 CDF를 만든 후 역으로 PDF를 도출했다. [본문으로]
크리에이티브 커먼즈 라이센스
Creative Commons License
2011/11/10 13:03 2011/11/10 13:03

트랙백 주소 :: 이 글에는 트랙백을 보낼 수 없습니다

댓글을 달아 주세요

  1. parkpd 2011/11/12 18:19  댓글주소  수정/삭제  댓글쓰기

    왠지 전에도 물어본 거 같지만
    여기에 들어간 수식을 http://www.codecogs.com/latex/eqneditor.php 에서 일일이 입력해서 이미지 받아와서 쓰고 계시나요?
    아니면 블로그 작성툴에서 LaTeX 를 지원하나요? 어떤 방식으로 수식 입력하고 계시나요?

  2. Hybrid 2011/11/13 09:19  댓글주소  수정/삭제  댓글쓰기

    텍스트큐브 플러그인 만들어서 쓰고 있어요ㅎㅎ 글쓰면서 LaTeX 형식으로 적어 놓으면 자동으로 변환돼요.

  3. parkpd 2011/11/13 11:29  댓글주소  수정/삭제  댓글쓰기

    저도 이번에 아는 분 도움받아서 위키에 LaTeX 플러그인 설치했거든요.
    http://bluebrown.net/moniwiki/wiki.php/MoniWikiPlugin
    Hybrid 님은 텍스트큐브 플러그인 어떻게 만드셨는지 한 번 소개해 주시지 않겠어요?
    이미 블로깅 하셨을려나?

  4. 우킷스 2012/06/13 18:36  댓글주소  수정/삭제  댓글쓰기

    좋은 글 감사합니다.
    사실 풀이에 대해서는 100% 이해 되지 않지만, 바로 사용할 수 있게끔 결론을 내주시니 감사히 응용하겠습니다.
    구독하고 종종 들리겠습니다.

    • Hybrid 2012/06/14 00:31  댓글주소  수정/삭제

      감사합니다.
      다시 보면 좀 설명에 아쉬운 것들이 있어서 기회가 되면 좀 더 보충해서 써볼까 합니다.ㅎ