조건부확률과 독립
개념
사건 \(B\)가 일어났다는 것을 알 때 사건 \(A\)가 일어날 확률을 조건부확률이라 하고, 다음과 같이 정의합니다.
\[P(A \mid B) = \frac{P(A \cap B)}{P(B)} \quad (P(B) > 0)\]
“비 오는 날”이라는 정보를 알면 “지각”의 확률이 달라지듯, 조건부확률은 새 정보로 확률을 다시 재는 것입니다.
이 정의를 정리하면 두 사건이 함께 일어날 확률을 곱으로 구하는 확률의 곱셈정리가 됩니다.
\[P(A \cap B) = P(B)\,P(A \mid B) = P(A)\,P(B \mid A)\]
카드를 연달아 뽑을 때처럼 앞 사건이 뒤 사건의 확률을 바꾸는 경우, 두 사건이 잇따라 일어날 확률은 이 곱셈정리로 구합니다. 한편 조건 \(B\)를 알아도 \(A\)의 확률이 변하지 않으면, 즉 \(P(A \mid B) = P(A)\)이면 두 사건은 서로 독립이라 하고, 이때 곱셈정리는 \(P(A \cap B) = P(A)\,P(B)\)로 간단해집니다. 그렇지 않으면 서로 종속입니다. 아래 앱은 학생 100명을 정사각형 100칸으로 나타냅니다. 사건 \(A\)는 “아침 운동을 함”, 사건 \(B\)는 “아침밥을 먹음”입니다. \(P(A)\), \(P(B \mid A)\), \(P(B \mid A^c)\)를 움직여 네 영역의 칸 수가 어떻게 변하는지, 그리고 언제 두 사건이 독립이 되는지 살펴보세요.
만지며 배우기
#| '!! shinylive warning !!': |
#| shinylive does not work in self-contained HTML documents.
#| Please set `embed-resources: false` in your metadata.
#| standalone: true
#| viewerHeight: 660
# matplotlib·numpy 없이 stdlib + 인라인 SVG 로만 그린다
from shiny import App, render, ui
ACCENT = "#2563eb"
INK = "#111827"
MUTED = "#6b7280"
def counts(pa, pba, pbac):
n_a = round(100 * pa)
n_ab = min(round(100 * pa * pba), n_a)
n_acb = min(round(100 * (1 - pa) * pbac), 100 - n_a)
return n_a, n_ab, n_acb
def grid_svg(n_a, n_ab, n_acb):
cell, gap, ox, oy = 24, 3, 6, 6
body = ""
for i in range(100):
c, r = i % 10, i // 10
x, y = ox + c * (cell + gap), oy + r * (cell + gap)
if i < n_ab:
fill, stroke = ACCENT, ACCENT
elif i < n_a:
fill, stroke = "none", ACCENT
elif i < n_a + n_acb:
fill, stroke = "#9ca3af", "#9ca3af"
else:
fill, stroke = "none", "#d1d5db"
body += (f'<rect x="{x}" y="{y}" width="{cell}" height="{cell}" rx="3" '
f'fill="{fill}" stroke="{stroke}" stroke-width="1.4"/>')
gx = ox + 10 * (cell + gap) + 18
legend = [
(f"A∩B ({n_ab})", ACCENT, ACCENT),
(f"A만 ({n_a - n_ab})", "none", ACCENT),
(f"B만 ({n_acb})", "#9ca3af", "#9ca3af"),
(f"둘 다 아님 ({100 - n_a - n_acb})", "none", "#d1d5db"),
]
for j, (lab, fill, stroke) in enumerate(legend):
yy = oy + 8 + j * 30
body += (f'<rect x="{gx}" y="{yy}" width="18" height="18" rx="3" '
f'fill="{fill}" stroke="{stroke}" stroke-width="1.4"/>'
f'<text x="{gx+26}" y="{yy+14}" font-size="12" fill="{INK}">{lab}</text>')
W, H = gx + 170, oy + 10 * (cell + gap)
return (f'<svg viewBox="0 0 {W} {H}" style="width:100%;height:auto;'
f'font-family:-apple-system,sans-serif;">{body}</svg>')
app_ui = ui.page_sidebar(
ui.sidebar(
ui.input_slider("pa", "P(A) — 아침 운동을 하는 비율",
min=0.1, max=0.9, value=0.4, step=0.05),
ui.input_slider("pba", "P(B|A) — 운동하는 학생 중 아침밥",
min=0.0, max=1.0, value=0.8, step=0.05),
ui.input_slider("pbac", "P(B|Aᶜ) — 운동 안 하는 학생 중 아침밥",
min=0.0, max=1.0, value=0.5, step=0.05),
width=240,
),
ui.card(
ui.card_header("학생 100명 — A: 아침 운동, B: 아침밥"),
ui.output_ui("grid"),
),
ui.card(ui.output_ui("readout")),
fillable=True,
)
def server(input, output, session):
@render.ui
def grid():
n_a, n_ab, n_acb = counts(input.pa(), input.pba(), input.pbac())
return ui.HTML(grid_svg(n_a, n_ab, n_acb))
@render.ui
def readout():
pa, pba, pbac = input.pa(), input.pba(), input.pbac()
pb = pa * pba + (1 - pa) * pbac
if pb == 0:
return ui.HTML(
'<p class="hs-readline">P(B) = 0이라 조건부확률 '
"P(A|B)는 정의되지 않습니다. P(B|A)나 P(B|Aᶜ)를 "
"0보다 크게 올려 보세요.</p>"
)
pab = pa * pba / pb
if abs(pba - pb) < 0.005:
indep = ("P(B|A)와 P(B)가 같으므로 두 사건은 서로 "
"독립입니다 — 운동 여부가 아침밥 확률을 바꾸지 않습니다.")
elif pba > pb:
indep = (f"P(B|A) = {pba:.2f} > P(B) = {pb:.2f}이므로 두 사건은 "
"서로 종속입니다 — 운동하는 학생이 아침밥을 더 잘 먹습니다.")
else:
indep = (f"P(B|A) = {pba:.2f} < P(B) = {pb:.2f}이므로 두 사건은 "
"서로 종속입니다 — 운동하는 학생이 아침밥을 덜 먹습니다.")
return ui.HTML(
f'<p class="hs-readline">'
f"전체에서 아침밥을 먹을 확률은 P(B) = P(A)P(B|A) + P(Aᶜ)P(B|Aᶜ) = "
f"{pb:.2f}입니다. 아침밥을 먹은 학생이 운동도 했을 조건부확률은 "
f"P(A|B) = P(A)P(B|A)/P(B) = {pab:.2f}입니다. {indep}</p>"
)
app = App(app_ui, server)
앱의 핵심 계산은 이 몇 줄이 전부입니다.
pa = 0.4 # P(A): 아침 운동
pba = 0.8 # P(B|A)
pbac = 0.5 # P(B|Aᶜ)
pb = pa * pba + (1 - pa) * pbac # 전체확률 P(B) = 0.62
pab = pa * pba / pb # P(A|B) ≈ 0.516 (베이즈)
print(pb, pab)
print("independent" if abs(pba - pb) < 1e-9 else "dependent")스스로 확인
두 값이 같으면 \(P(B) = P(B \mid A) = P(B \mid A^c)\)가 되어 \(A\)와 \(B\)는 서로 독립이 됩니다. 운동을 하든 안 하든 아침밥을 먹을 확률이 같다는 뜻입니다. 격자에서 \(A\) 영역과 \(A^c\) 영역의 색칠 비율이 같아지는 것을 확인해 보세요.
전체확률로 \(P(B) = 0.4 \times 0.8 + 0.6 \times 0.5 = 0.62\), 따라서 \(P(A \mid B) = \dfrac{P(A \cap B)}{P(B)} = \dfrac{0.32}{0.62} \approx 0.52\) 입니다. 아침밥을 먹었다는 정보만으로 운동했을 확률이 \(0.4\)에서 \(0.52\)로 올라갑니다 — 정보가 확률을 갱신한 것입니다.