본문 바로가기

Theory/Algorithms

몬테카를로 시뮬레이션 (4) - 범용 몬테카를로 엔진

반응형

몬테카를로 시뮬레이션 (1) - 파이 계산하기

몬테카를로 시뮬레이션 (2) - 온라인 판매자 예제

몬테카를로 시뮬레이션 (3) - 부트스트랩 알고리즘 (bootstrap)


이제까지 다뤘던 몬테카를로 포스트들을 기반으로 일반적으로 사용할 수 있는 범용 몬테카를로 엔진을 구현해보도록 하겠습니다. MCEngine 클래스는 여러 일반적인 몬테카를로 계산 및 시뮬레이션 문제들이 상속하여 사용할 수 있는 부모 클래스로서 "simulate_once", "simulate_many" 메소드로 구성됩니다.

class MCEngine:
    """
    Monte Carlo Engine parent class.
    Runs a simulation many times and computes average and error in average.
    Must be extended to provide the simulate_once method
    """

    def simulate_once(self):
        raise NotImplementedError
  • "simulate_once" 메소드는 MCEngine 클래스를 상속한 하위 몬테카를로 문제 클래스에서 각각 특정한 계산에 대해  구체적으로 구현되어야 하기 때문에 이 클래스에서는 별도로 구현되지 않습니다. 
    def simulate_many(self, ap=0.1, rp=0.1, ns=1000):
        self.results = []
        s1 = s2 = 0.0
        self.convergence = False
        for k in range(1, ns):
            x = self.simulate_once()
            self.results.append(x)
            s1 += x
            s2 += x * x
            mu = float(s1) / k
            variance = float(s2) / k - mu * mu
            dmu = sqrt(variance / k)
            if k > 10:
                if abs(dmu) < max(ap, abs(mu) * rp):
                    self.converence = True
                    break
        self.results.sort()
        return bootstrap(self.results)
  • "simulate_many" 메소드는 "simulate_once" 메소드를 반복적으로 호출하여 평균과 오차를 통해 수렴하는지 검사합니다. 또한, 시뮬레이션 결과들에 대하여 부트스트랩 샘플링을 통해 오차를 계산하여 모집단의 평균을 추정합니다.

 

추가적으로 var (value at risk, 최대예상손실액) 함수를 구현합니다. 이 함수는 주어진 신뢰 수준에 따른 시뮬레이션의 출력값을 출력합니다. 예를 들어 신뢰 수준이 95%라 한다면, 95% 확률로 시뮬레이션 출력값이 이 함수가 계산하는 수치보다 작아야 한다는 것이죠.

    def var(self, confidence=95):
        index = int(0.01 * len(self.results) * confidence + 0.999)
        if len(self.results) - index < 5:
            raise ArithmeticError("not enough data, not reliable")
        return self.results[index]
  • index를 계산하는 과정에서 0.999를 더해주는 이유는 파이썬의 int 내장함수는 내림으로 동작하기 때문입니다. (int(1.5) == 1) 

 

구현한 범용 몬테카를로 엔진을 이용해 [알고리즘 & 코딩테스트/알고리즘] - 몬테카를로 시뮬레이션 (1) - 파이 계산하기 에서 구현한 $\pi$를 다시 계산해보도록 하겠습니다.

class PiSimulator(MCEngine):
    def simulate_once(self):
        return 4. if (random.random()**2 + random.random()**2) < 1 else 0. 

s = PiSimulator()
s.simulate_many(ns=2000)

>>> (2.838709677419355, 3.096774193548387, 3.3548387096774195)
  • 신뢰 수준 68%로 $\pi$의 값을 계산해보면 2.838과 3.354 사이에 있고 근사치는 3.096임을 알 수 있습니다.

 


몬테카를로 시뮬레이션 (5) - 적분 계산하기

반응형