기본 콘텐츠로 건너뛰기

[matplotlib] 등고선(Contour)

[data analysis] 베이즈정리 (Bayes theorem)

베이즈정리 (Bayes theorem)

관련된 내용

예 1)

표 1은 사무실 lamp을 생산하는 공장 A, B, C의 생산율과 불량품율에 대한 자료입니다.

표 1 공장별 생산에 대한 자료
공장 Product D, P(D|Product)
A 0.35 0.015
B 0.35 0.01
C 0.3 0.02
Product: 생산율, D: 불량률

생산된 불량품이 각 공장에서 생산되었을 확률?

공장 C에서 생산되었을 확률은 식1과 같이 나타낼 수 있습니다.

$$P(C\,|\, D) = \frac{P(C\, ∩\, D)}{P(D)}$$(식 1)

표 1에서 공장 C에서의 불량품율에 대한 정보를 사용할 수 있습니다. 즉, P(D|C)은 식 2와 같이 계산할 수 있습니다.

$$ P(D\, |\, C) = \frac{P(D\, ∩ \,C)}{P(C)}$$(식 2)

교집합은 교환법칙이 성립하므로 P(D ∩ C) = P(C ∩ D)로 치환할 수 있습니다(식 3).

\begin{align} P(C \,∩\, D)& = P(D\,|\,C)P(C)\\&= 0.020·0.3\\&=0.006\end{align} (식 3)

P(D)는 각 공장에서의 불량품 확률의 합과 같습니다(식 4).

\begin{align}P(D)&= P(D\,∩\,A) + P(D\,∩\,B) + P(D\,∩\,C)\\ &= P(D\,|\,A)P(A) + P(D\,|\,B)P(B) +P(D\,|\,C)P(C)\\ &= 0.015·0.35 + 0.01·0.35 + 0.02·0.30\\ &= 0.01475\end{align}(식 4)
A=np.array([0.35, 0.015])
B=np.array([0.35, 0.01])
C=np.array([0.3, 0.02])
data=pd.DataFrame(np.c_[A, B, C], index=["P(factory)","P(D|factory)"], columns=["A","B","C"]).T
data 
P(factory)P(D|factory)
A 0.35 0.015
B 0.35 0.010
C0.30 0.020
dat=data.values
D_tot=np.sum(np.prod(dat, axis=1))
print(D_tot)
0.01475

위 결과를 적용하면 불량품 D가 공장 C에서 생산되었을 확률 즉, 식 2의 계산결과는 다음과 같습니다.

DC=dat[2,0]*dat[2, 1]/D_tot
round(DC, 3)
0.407

P(D|C)와 같은 방법으로 공장 A, B에서 불량품을 생산할 확률을 계산해 봅니다(식 5).

\begin{align} P(A\, | \,D) &= \frac{P(A\, ∩ \,D)}{P(D)}\\ & = \frac{P(D\,|\,A)P(A)}{P(D)}\\P(B\, | \,D) &=\frac{P(B\, ∩ \,D)}{P(D)}\\ &= \frac{P(D\,|\,BB)}{P(D)}\end{align}(식 5)
AC=dat[0,0]*dat[0, 1]/D_tot
round(AC, 3)
0.356
BC=dat[1,0]*dat[1, 1]/D_tot
round(BC, 3)
0.237

위 예에서 P(A), P(B), P(C)는 부가적인 정보를 계산하기 전에 얻을 수 있는 확률로서 사전확률 (prior probability)라고 합니다. 이 사전확률들을 기반으로 계산할 수 있는 조건부확률 P(A|D), P(B|D), P(C|D)를 사후확률 (posterior probability)라고 합니다. 즉, 사후확률은 사전확률로부터 불량품률과 같은 부가적인 정보를 획득한 후에 어떤 사건의 조건부 확률을 계산할 수 있는 확률을 의미합니다. 위의 과정을 일반화한 정리를 베이즈정리 (Bayes theorem)이라 합니다.

[베이즈정리 (Bayes theorem)]

표본 공간 S에서 여러 부분공간들(B1, B2, · · · , Bk)이 독립인 경우 식 6과 같이 나타낼 수 있습니다.

$$S = B_1\, ∪ B_2\, ∪ … ∪B_k$$ (식 6)

표본 공간의 모든 사건이 독립이므로 표본 공간과 연관된 사건 A의 총 발생은 식 7과 같이 A를 조건으로 하는 모든 발생들의 합과 같습니다.

\begin{align}A&=(A\,\cap\,B_1)\,\cup\,(A\,\cap\,B_2)\,\cup\,\cdots\,\cup\,(A\,\cap\,B_k)\\ P(A)&=P(A\,\cap\,B_1)\,\cup\,P(A\,\cap\,B_2)\,\cup\,\cdots\,\cup\,P(A\,\cap\,B_k)\\ &=\sum^k_{i=1}P(A\,\cap\,B_i)\\&=\sum^k_{i=1}P(A\,\vert\,B_i)P(B_i)\end{align} (식 7)

위의 관계로 부터 Bk의 사후확률은 식 8이 같이 계산됩니다.

\begin{align}P(B_k\,\vert\,A)&=\frac{P(B_k\,\cap\,A)}{P(A)}\\&= \frac{P(A\,\vert\,B_k)P(B_k)}{\sum^k_{i=1}P(A\,\vert\, B_i)P(B_i)} \end{align} (식 8)

예 2)

공구함에 포함되어 있는 40개의 퓨즈들 중에 5개는 완전한 불량품(D)이고 10개는 1시간 동안 지속되는 부분불량품(pD), 나머지 25개는 정상품(G)입니다. 한 개가 선택되는 경우 완전한 불량품이 아닌 상품을 선택할 확률?

퓨즈를 불량품과 불량(D)이 아닌 제품(ND)로 분류한다면 G는 ND에 포함되어 있습니다. 그러므로 문제의 조건부 확률 P(G|ND)는 식 9와 같이 계산됩니다.

\begin{align}P(G\, ∩ \,ND) &= P(G)\\ P(G \,|\, ND) &= \frac{P(G \,∩ \,ND)}{P(ND)}\\&=\frac{P(G)}{P(ND)}\end{align} (식 9)
PD=5/40
Ppd=10/40
PG=25/40
PND=PG+Ppd
condPG_ND=PG/PND
print(round(condPG_ND, 3))
0.714

예 3)

A에게 두 아이가 있는데 가장 어린 아들과 함께 어떤 모임에 참석해야 합니다. 그가 그 모임에 참석할 수 있다면 그의 가족에 두 아들들만이 포함될 확률?

  • 표본공간 S={(b,b), (b,g), (g, b), (g,g)}, b:boy, g: girl
  • 참석 조건에 부합하는 모든 사건 A={(b,b), (g, b)}
  • 대상이 되는 사건 B={(b,b)}

위 조건을 근거로 P(B|A)는 식 9와 같이 계산됩니다.

\begin{align}P(B\, | \,A) &= \frac{P(B\, ∩ \,A)}{P(A)}\\&=\frac{P(B)}{P(A)}\end{align}(식 9)
S=4
PA=2/S
PB=1/S
PB_A=PB/PA
PB_A
0.5

예 4)

다음 자료는 일정기간 kospi(kos)와 kodaq(kq)의 종가(Closing price)들에 대한 2일간의 변화에 대한 것으로 증가를 1, 하락을 0으로 목록화 한 것입니다. 두 종목의 가격 변동은 독립일까요?

kospi: [1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1]
kosdaq: [1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1]

이 자료는 파이썬 패키지 FinanceDataReader를 사용하여 호출한 일일 자료를 조정한 것으로 다음 코드를 사용하여 작성한 것입니다.

import FinanceDataReader as fdr
import pandas as pd
st=pd.Timestamp(2023, 2, 20) #(1)
et=pd.Timestamp(2023, 3,20)  
kos=fdr.DataReader('KS11', st, et)['Close'] #(2)
kq=fdr.DataReader('KQ11', st, et)['Close']
kos1=kos.pct_change()
kos1=kos1.replace(0, method='ffill')  #(3)
kos1=kos1.dropna() #(4)
kq1=kq.pct_change() #(5)
kq1=kq1.replace(0, method="ffill")
kq1=kq1.dropna()
kos2=pd.cut(kos1, bins=[-1, 0, 1],labels=[0, 1])  #(6)
kq2=pd.cut(kq1, bins=[-1, 0, 1],labels=[0, 1])
data= pd.concat([kos2, kq2], axis=1)  # (7)
data.index=range(1, len(kos2)+1)
data
Close Closel
1 1 1
2 0 0
3 1 1
16 1 1
17 0 1
18 1 1

위 코드에 사용한 코드는 다음과 같습니다.

코드 번호함수/메소드내용
(1) Timesptamp()날짜 데이터를 생성하는 것으로 수치형을 날짜형으로 변환
(2) DataReader() 호출한 자료는 DataFrame 형식으로 열이름은 'Open','High','Low','Close', 'Volume', 'Change'등을 포함합니다. 이중에 'Close'만을 선택
(3) .replace()특정한 값을 지정한 값으로 변환. 자료 중 0을 앞 행의 값으로 변환
(4) .dropna() 자료 중 결측치 값을 포함한 행을 제거
(5) .pct_change()같은 열의 2개의 행간의 변화율을 계산
(6) .cut()연속변수의 구간을 설정하여 categorical 변수로 전환
(7) .concat()두 DataFrame 객체를 결합

두 집단의 독립여부는 교집합을 고려하여 판단할 수 있습니다. 즉, 독립사건들의 교집합에 대한 확률은 두 확률의 곱으로 계산됩니다. 두 집단이 독립이라면 식 10과 같이 그 두 확률의 곱 결과는 조건부 확률에 의한 결과와 같을 것입니다.

P(kos = 1) ∩ P(kq = 1) = P(kos = 1|kq = 1)P(kq = 1)(식 10)
→ 독립인 경우 P(kos = 1) ∩ P(kq = 1) = P(kos = 1) * P(kq = 1)

위 표에 대한 교차표를 작성해 봅니다. 이는 pd.crosstab() 함수를 사용합니다.

  • pd.crosstab(index, columns, rownames=None, colnames=None, margins=False, margins_name= 'All', dropna= True, normalize=False)
    • 두 개 (또는 그 이상)의 요인(factor)에 대한 교차표를 작성합니다.
    • index, columns : 각각 행과 열에서 그룹화 할 값
    • rownames, colnames: 표의 행과 열의 이름
    • margins=True → 행합과 열합을 마지막 행과 열에 첨부, 그 행과 열의 이름은 margins_name으로 지정할 수 있음
    • dropna=True이면 NA 값은 삭제. 행과 열의 수가 일치하지 않을 경우는 False를 선택 즉, 행과 열의 수가 일치하지 않을 경우 True이면 행 기준의 합과 열의 합 사이에 불일치가 발생
    • 값들의 정규화의 여부를 지정. 이 인수에 전달 할 수 있는 인수값은 다음과 같습니다.
      • normalize=True or all 이면 각 값은 총합으로 나눈 값을 반환
      • normalize=index, 각 행에 대해 정규화
      • normalize=column, 각 열에 대해 정규화
kos= np.array([1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1])
kq= np.array([1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1])
ct=pd.crosstab(kos, kq, rownames=['kospi'], colnames=['kq'], margins=True)
ct
kq 0 1 All
kospi
0 6 2 8
1 2 8 10
All 8 10 18

P(kos = 1) * P(kq = 1)의 결과

round(ct.iloc[1,2]/18*ct.iloc[1,2]/18, 4)
0.3086

P(kos = 1) ∩ P(kq = 1)의 결과

round(ct.iloc[1,1]/18, 4)
0.4444

위 두 결과가 같지 않으므로 독립이 아닙니다.

댓글