포아송 과정

확률 통계
공개

2025년 7월 4일

연습문제

8-1

from scipy.stats import gamma
import numpy as np
from empiricaldist import Pmf
import matplotlib.pyplot as plt

plt.rcParams['font.family'] = 'Noto Sans KR'

alpha = 1.4
qs = np.linspace(0, 10, 101)
ps = gamma.pdf(qs, alpha)
prior = Pmf(ps, qs)
prior.normalize()
9.889360237140306
def expo_pdf(t, lam):
    return lam * np.exp(-lam * t)

t1 = 11/90
likelihood1 = expo_pdf(t1, prior.qs)
post1 = prior * likelihood1
post1.normalize()

# 지수분포에서 모든 시행은 독립적
t2 = 12/90
likelihood2 = expo_pdf(t2, post1.qs)
post2 = post1 * likelihood2
post2.normalize()

prior.plot(label="사전분포", alpha=0.7)
post1.plot(label="1골 득점 후 사후분포", alpha=0.7)
post2.plot(label="2골 득점 후 사후분포", alpha=0.7)
plt.xlabel("λ (게임당 골 수)")
plt.ylabel("확률밀도")
plt.title("독일의 골 득점률 분포")
plt.legend()
plt.show()

from scipy.stats import poisson
import pandas as pd
import numpy as np

def make_poisson_pmf(lam, qs):
    ps = poisson.pmf(qs, lam)
    pmf = Pmf(ps, qs)
    pmf.normalize()
    return pmf

def make_mixture(pmf, pmf_seq):
    df = pd.DataFrame(pmf_seq).fillna(0).transpose()
    df *= np.array(pmf)
    total = df.sum(axis=1)
    return Pmf(total)

remaining_time = (90 - 23) / 90
goals = np.arange(15)
pmf_seq = [make_poisson_pmf(lam * remaining_time, goals) for lam in post2.qs]
pred = make_mixture(post2, pmf_seq)

print(f"예상 골 수: {sum(pred.qs[i] * pred.ps[i] for i in range(len(pred.qs))):.2f}골")
# 표준편차 수동 계산
mean_val = sum(pred.qs[i] * pred.ps[i] for i in range(len(pred.qs)))
variance = sum((pred.qs[i] - mean_val)**2 * pred.ps[i] for i in range(len(pred.qs)))
std_val = variance**0.5
print(f"표준편차: {std_val:.2f}골")

# 5골 이상 득점할 확률 계산
prob_5_or_more = 1 - sum(pred.ps[i] for i in range(min(5, len(pred.ps))))
print(f"\n5골 이상 득점할 확률: {prob_5_or_more:.4f} ({prob_5_or_more*100:.2f}%)")

pred.plot(color='red', alpha=0.7)
plt.axvline(5, color='orange', linestyle='--', alpha=0.8, label='5골')
try:
    # 수동으로 평균 계산
    mean_goals = sum(pred.qs[i] * pred.ps[i] for i in range(len(pred.qs)))
    plt.axvline(mean_goals, color='blue', linestyle='--', alpha=0.8, label=f'평균 ({mean_goals:.2f}골)')
except:
    print("평균 계산 중 오류 발생")
plt.xlabel("골 수")
plt.ylabel("확률")
plt.title("남은 시간 동안의 예상 골 수 분포")
plt.legend()
plt.show()
예상 골 수: 2.01골
표준편차: 1.78골

5골 이상 득점할 확률: 0.0939 (9.39%)

8-2

def update_goal(prior, data):
    posterior = prior.copy()
    for goals in data:
        likelihood = [poisson.pmf(goals, lam) for lam in posterior.qs]
        posterior = posterior * likelihood
        posterior.normalize()
    return posterior
france = update_goal(prior, [4])
croatia = update_goal(prior, [2])

qs = np.linspace(0, 1, 101)
likelihood = expo_pdf(qs, prior.qs)

france_post = france * likelihood
france_post.normalize()
croatia_post = croatia * likelihood
croatia_post.normalize()

Pmf.prob_lt(france_post, croatia_post)
0.2633977680689847

8-3

alpha = 2.8
qs = np.linspace(0, 10, 101)

prior = Pmf(gamma.pdf(qs, alpha), qs)
prior.normalize()


boston_posterior = update_goal(prior, [0, 2, 8, 4])
vancouver_posterior = update_goal(prior, [1, 3, 1, 0])

prior.plot(label='prior')
boston_posterior.plot(label='boston')
vancouver_posterior.plot(label='vancouver')
plt.legend()

pmf_seq = [make_poisson_pmf(lam, goals) for lam in prior.qs]
pred_boston = make_mixture(boston_posterior, pmf_seq)
pred_vancouver = make_mixture(vancouver_posterior, pmf_seq)
win = Pmf.prob_gt(pred_boston, pred_vancouver)
win
0.703863141313654

챔피언십 우승 확률은 아직은 못 구하겠다.

맨 위로