Matplotlib 을 이용한 베이즈 업데이트

Beginner

This tutorial is from open-source community. Access the source code

소개

베이즈 업데이트는 새로운 데이터가 사용 가능해짐에 따라 가설의 확률을 업데이트할 수 있게 해주는 통계적 접근 방식입니다. 이 랩에서는 Matplotlib 을 사용하여 베이즈 업데이트가 어떻게 작동하는지 보여주는 애니메이션을 만들 것입니다. 구체적으로, 우리는 동전 던지기 실험을 시뮬레이션하고 베이즈 업데이트를 사용하여 동전이 앞면으로 나올 확률을 추정할 것입니다.

VM 팁

VM 시작이 완료되면, 왼쪽 상단을 클릭하여 Notebook 탭으로 전환하여 실습을 위해 Jupyter Notebook에 접근하십시오.

때로는 Jupyter Notebook 이 로딩을 완료하는 데 몇 초 정도 기다려야 할 수도 있습니다. Jupyter Notebook 의 제한으로 인해 작업의 유효성 검사는 자동화될 수 없습니다.

학습 중에 문제가 발생하면 언제든지 Labby 에게 문의하십시오. 세션 후 피드백을 제공해주시면 문제를 신속하게 해결해 드리겠습니다.

필요한 라이브러리 가져오기

랩에서 사용할 라이브러리를 가져오는 것으로 시작합니다. 구체적으로, 시각화를 위해 matplotlib.pyplot, 수치 계산을 위해 numpy, 수학 함수를 위해 math를 사용할 것입니다.

import math

import matplotlib.pyplot as plt
import numpy as np

베타 분포 PDF 정의

베타 분포는 확률의 분포를 나타내는 데 자주 사용되는 연속 확률 분포입니다. 베이즈 업데이트에서 우리는 베타 분포를 사전 분포 (prior distribution) 로 사용하여 데이터를 관찰하기 전에 가설의 확률에 대한 우리의 믿음을 나타냅니다. 그런 다음 새로운 데이터를 관찰하면서 베타 분포를 업데이트합니다.

베이즈 업데이트를 시뮬레이션하기 위해, 베타 분포의 확률 밀도 함수 (PDF, Probability Density Function) 를 계산하는 함수를 정의해야 합니다. 베타 분포 PDF 에 사용되는 감마 함수를 계산하기 위해 math.gamma 함수를 사용할 수 있습니다.

def beta_pdf(x, a, b):
    return (x**(a-1) * (1-x)**(b-1) * math.gamma(a + b)
            / (math.gamma(a) * math.gamma(b)))

UpdateDist 클래스 정의

다음으로, 새로운 데이터가 관찰될 때 베타 분포를 업데이트하는 데 사용될 UpdateDist라는 클래스를 정의합니다. UpdateDist 클래스는 두 개의 인수를 받습니다: Matplotlib 축 객체와 초기 성공 확률입니다.

class UpdateDist:
    def __init__(self, ax, prob=0.5):
        self.success = 0
        self.prob = prob
        self.line, = ax.plot([], [], 'k-')
        self.x = np.linspace(0, 1, 200)
        self.ax = ax

        ## Set up plot parameters
        self.ax.set_xlim(0, 1)
        self.ax.set_ylim(0, 10)
        self.ax.grid(True)

        ## This vertical line represents the theoretical value, to
        ## which the plotted distribution should converge.
        self.ax.axvline(prob, linestyle='--', color='black')

__init__ 메서드는 초기 성공 횟수를 0 (self.success = 0) 으로 설정하고 초기 성공 확률을 인수로 전달된 값 (self.prob = prob) 으로 설정하여 클래스 인스턴스를 초기화합니다. 또한 베타 분포를 나타내는 선 객체를 생성하고 플롯 매개변수를 설정합니다.

__call__ 메서드는 애니메이션이 업데이트될 때마다 호출됩니다. 이 메서드는 동전 던지기 실험을 시뮬레이션하고 그에 따라 베타 분포를 업데이트합니다.

def __call__(self, i):
        ## This way the plot can continuously run and we just keep
        ## watching new realizations of the process
        if i == 0:
            self.success = 0
            self.line.set_data([], [])
            return self.line,

        ## Choose success based on exceed a threshold with a uniform pick
        if np.random.rand() < self.prob:
            self.success += 1
        y = beta_pdf(self.x, self.success + 1, (i - self.success) + 1)
        self.line.set_data(self.x, y)
        return self.line,

애니메이션의 첫 번째 프레임인 경우 (if i == 0), 성공 횟수를 0 으로 재설정하고 선 객체를 지웁니다. 그렇지 않으면 0 과 1 사이의 난수를 생성 (np.random.rand()) 하고 이를 성공 확률 (self.prob) 과 비교하여 동전 던지기 실험을 시뮬레이션합니다. 난수가 성공 확률보다 작으면 성공으로 간주하고 beta_pdf 함수를 사용하여 베타 분포를 업데이트합니다. 마지막으로, 새로운 데이터로 선 객체를 업데이트하고 반환합니다.

애니메이션 생성

이제 UpdateDist 클래스를 정의했으므로 Matplotlib 의 FuncAnimation 클래스를 사용하여 애니메이션을 생성할 수 있습니다. figure 객체와 axis 객체를 생성하고 axis 객체를 UpdateDist 클래스에 전달하여 클래스의 새 인스턴스를 생성합니다.

fig, ax = plt.subplots()
ud = UpdateDist(ax, prob=0.7)
anim = FuncAnimation(fig, ud, frames=100, interval=100, blit=True)
plt.show()

FuncAnimation 클래스는 여러 인수를 받습니다:

  • fig: figure 객체
  • ud: UpdateDist 인스턴스
  • frames: 애니메이션할 프레임 수
  • interval: 프레임 간의 시간 간격 (밀리초)
  • blit: 변경된 플롯의 부분만 업데이트할지 여부

결과 해석

애니메이션은 새로운 데이터가 관찰됨에 따라 베타 분포가 어떻게 업데이트되는지 보여줍니다. 검은색 점선은 실제 성공 확률 (즉, 동전이 앞면으로 나올 확률) 을 나타냅니다. 애니메이션이 진행됨에 따라 베타 분포는 사전 성공 확률 (0.7) 에서 정점을 시작하여 더 많은 데이터가 관찰됨에 따라 점차 실제 성공 확률로 이동하는 것을 볼 수 있습니다.

요약

이 랩에서는 Matplotlib 을 사용하여 베이즈 업데이트를 시연하는 애니메이션을 만들었습니다. 베타 분포 PDF 를 계산하는 함수와 새로운 데이터가 관찰됨에 따라 베타 분포를 업데이트하는 클래스를 정의했습니다. 그런 다음 Matplotlib 의 FuncAnimation 클래스를 사용하여 애니메이션을 생성하고 결과를 해석했습니다.