import numpy as np
from empiricaldist import Pmf
= np.arange(1, 1001)
hypos = Pmf(1, hypos) prior
수량 추정
확률 통계
기관차 문제
- 각 철도를 지나가는 기관차에 1부터 N까지의 순서로 번호를 붙인다.
- 60번 번호가 붙은 기관차를 보았다.
- 이 철도에 몇 개의 기관차가 지나가는지 추정해보자
- 가정: N은 1부터 1000까지의 값 중 한 값이 동일한 확률로 선택될 수 있다.
def update_train(pmf, data):
= pmf.qs
hypos = 1 / hypos
likelihood > hypos)] = 0
likelihood[(data *= likelihood
pmf pmf.normalize()
= 60
data = prior.copy()
posterior update_train(posterior, data)
import matplotlib.pyplot as plt
'font.family'] = 'Noto Sans KR'
plt.rcParams[
='60번 기관차 발견 시 전체 기관차 수의 사후확률', color='C5')
posterior.plot(label
plt.legend()'사후 확률')
plt.title('기관차 수')
plt.xlabel('PMF') plt.ylabel(
Text(0, 0.5, 'PMF')
posterior.max_prob()
60
- 당연하다는 듯이 60이 최선의 선택. 하지만 이는 별로 도움이 안됨.
- 대안으로 사후확률의 평균을 구해본다.
posterior.mean()
333.41989326370776
- 해당 값을 선택하는 것이 장기적으로 좋은 선택.
import pandas as pd
= pd.DataFrame(columns=['사후확률 분포 평균'])
df = '상한값'
df.index.name
= [30, 60, 90]
dataset
for high in [500, 1000, 2000]:
= np.arange(1, high+1)
hypos = Pmf(1, hypos)
pmf for data in dataset:
update_train(pmf, data)= pmf.mean()
df.loc[high] df
사후확률 분포 평균 | |
---|---|
상한값 | |
500 | 151.849588 |
1000 | 164.305586 |
2000 | 171.338181 |
- 하지만 상한값의 범위의 변화에 따른 사후확률 분포의 평균값이 크게 달라진다.
- 이럴때는 2가지 방법이 있다.
- 데이터를 더 확보
- 배경지식을 더 확보해서 더 나은 사전확률을 선택
멱법칙 사전확률
- 기관차 수는 멱법칙을 주로 따르는 것으로 알려져 있음
- 더 적합한 사전확률은 안정적인 사전확률을 제공할 수 있다.
= 1.0
alpha = hypos ** (-alpha)
ps = Pmf(ps, hypos, name='power law')
power power.normalize()
8.178368103610282
= Pmf(1, hypos, name='uniform')
uniform
uniform.normalize()
='power', color='skyblue')
power.plot(label='uniform', color='pink')
uniform.plot(label
plt.legend()'사전확률 분포')
plt.title('기관차 수')
plt.xlabel('PMF') plt.ylabel(
Text(0, 0.5, 'PMF')
60)
update_train(uniform, 60)
update_train(power,
='power', color='skyblue')
power.plot(label='uniform', color='pink')
uniform.plot(label
plt.legend()'사후확률 분포')
plt.title('기관차 수')
plt.xlabel('PMF') plt.ylabel(
Text(0, 0.5, 'PMF')
= pd.DataFrame(columns=['사후확률 분포 평균'])
df = '상한값'
df.index.name
= 1.0
alpha = [30, 60, 90]
dataset
for high in [500, 1000, 2000]:
= np.arange(1, high+1)
hypos = hypos**(-alpha)
ps = Pmf(ps, hypos)
power for data in dataset:
update_train(power, data)= power.mean()
df.loc[high] df
사후확률 분포 평균 | |
---|---|
상한값 | |
500 | 130.708470 |
1000 | 133.275231 |
2000 | 133.997463 |
신뢰구간
0.9) power.credible_interval(
array([ 91., 243.])
연습문제
5-1
from scipy.stats import binom
def update(pmf, k, p):
= binom.pmf(k, pmf.qs, p)
likelihood *= likelihood
pmf
pmf.normalize()
= np.arange(1, 2001)
hypos = Pmf(1, hypos)
prior
= prior.copy()
posterior
2, 1/365)
update(posterior, print(f"5월 11일 데이터 적용 후 평균 인원수: {posterior.mean():.1f}")
1, 1/365)
update(posterior, print(f"5월 23일 데이터 적용 후 평균 인원수: {posterior.mean():.1f}")
0, 1/365)
update(posterior, print(f"8월 1일 데이터 적용 후 평균 인원수: {posterior.mean():.1f}")
5월 11일 데이터 적용 후 평균 인원수: 957.1
5월 23일 데이터 적용 후 평균 인원수: 721.7
8월 1일 데이터 적용 후 평균 인원수: 486.2
= posterior.mean()
estimated_people print(f"추정된 강당 인원수: {estimated_people:.1f}명")
= posterior[posterior.qs > 1200].sum()
prob_over_1200 print(f"1200명을 초과할 확률: {prob_over_1200:.4f} ({prob_over_1200*100:.2f}%)")
= posterior.credible_interval(0.9)
ci_90 print(f"90% 신뢰구간: [{ci_90[0]:.0f}, {ci_90[1]:.0f}]")
추정된 강당 인원수: 486.2명
1200명을 초과할 확률: 0.0112 (1.12%)
90% 신뢰구간: [166, 942]
5-2
def rabbit_likelihood(n):
return ((n - 1) / n) * (1/n) * (1/n) * 3
= np.arange(4, 11)
hypos = Pmf(1, hypos)
prior
= [rabbit_likelihood(n) for n in hypos]
likelihood
= prior.copy()
posterior *= likelihood
posterior
posterior.normalize()
print(f"\n추정 토끼 수 (평균): {posterior.mean():.2f}마리")
추정 토끼 수 (평균): 5.92마리
5-3
def update_remain(pmf, data):
= pmf.qs
hypos = 1 / hypos
likelihood < data)] = 0
likelihood[(hypos *= likelihood
pmf
pmf.normalize()
= np.arange(0, 1096)
hypos = Pmf(1, hypos)
prior
prior.normalize()
1095)
update_remain(prior, ='사후확률', color='pink')
prior.plot(label
plt.legend() plt.show()
5-5
import numpy as np
from empiricaldist import Pmf
= np.arange(0, 201) # 10억 단위
hypos_short = Pmf(1, hypos_short, name="short")
prior_short
prior_short.normalize()
= np.arange(0, 2001)
hypos_long = Pmf(1, hypos_long, name="long")
prior_long
prior_long.normalize()
= {}
likelihood_ps for pmf in [prior_short, prior_long]:
= 1 / pmf.qs
likelihood < 108)] = 0
likelihood[(pmf.qs *= likelihood
pmf
pmf.normalize()= pmf(108)
likelihood_ps[pmf.name] =f"{pmf.name}: {pmf(108)}")
pmf.plot(label
plt.legend() plt.show()
= Pmf.from_seq(['short', 'long'])
prior for hypos in prior.index:
*= likelihood_ps[hypos]
prior.loc[hypos]
prior.normalize() prior
probs | |
---|---|
long | 0.175733 |
short | 0.824267 |