Python/Visualization

[Python] Monte Carlo algorithm

언킴 2022. 1. 14. 22:51
반응형

몬테카를로(Monte Carlo) 방법은 원하는 면적을 무한정 찍어서 그 면적을 구한다는 방식이라고 보면 된다. 정사각형 내에 원을 그리고 원의 면적을 구하고 싶다면 랜덤하게 점을 찍고 원 안에 들어간 점의 수와 전체 점을 찍은 수를 가지고 원 면적의 근삿값을 찾을 수 있을 것이다. 여기서는 몬테카를로 샘플링을 이용하여 원주율($pi$)을 근사해볼 생각이다.

 

import matplotlib.pyplot as plt
import numpy as np 
import math
import time

%matplotlib inline

plt.rcParams['axes.unicode_minus'] = False
plt.rcParams['font.family'] = 'NanumGothic'

 

plt.rcParams['axes.unicode_minus'] = False 의 경우는 폰트 문제로 인해 마이너스로 가면 폰트가 깨지는 것을 방지하기 위해서 False로 변환하였고, 그림에 한글은 들어가지 않지만 폰트를 나눔고딕체로 바꿔주기 위해 plt.rcParam['font.family']를 변경해주었다. 

 

circle_x = np.arange(0, 1, 0.001)
circle_y = np.sqrt(1 - np.power(circle_x, 2))

plt.figure(figsize = (10, 10))
plt.plot(circle_x, circle_y);

x는 0부터 1까지 0.001 간격으로 점을 찍었고, y의 경우 원방정식 ($ r^2 = x^2 + y^2$)으로 유도하여 y를 계산했다 이때 반지름은 1로 계산하였다.(반지름이 1이 아니라 다른 수로 설정하여 본인 입맛대로 해보는 것도 좋은 공부가 된다.)

 

한가지 흠이라고 하면 색을 설정하지 않고, 타이틀을 넣지 않아서 그림이 너무 없어보인다...

n = 1000
x = 0
plt.figure(figsize = (10, 10))
for _ in range(0, n):
    score_x = np.random.random()
    score_y = np.random.random()
    plt.plot(circle_x, circle_y)
    r = np.sqrt(np.power(score_x, 2) + np.power(score_y, 2))
    
    if r < 1:
        plt.scatter(score_x, score_y, color = 'blue')
        x += 1
    else:
        plt.scatter(score_x, score_y, color = 'black')

pi = 4 * x / n
print('pi 근사치 :', pi)
# 3.144
plt.show()

총 천 번 시행하였고, 만약에 원 안에 점이 찍히면 파란색 점을 찍게 설정하고, 원 밖에 점이 찍히면 검정색으로 점을 찍도록 설정해두었다. 만약 시행 횟수를 더 늘린다면 조금더 원주율에 가까운 수식을 산출할 수 있지 않을까 한다. 아무래도 확률값으로 찍다보니 간혹가다가 값이 살짝 이상하게 나올 수도 있지만, 시행횟수를 늘린다면 근접한 값이 나올 것이다. 퍼뮤테이션 방법 중 하나인 몬테카를로 샘플링을 다루어 보았다.