跳轉到

8.1 離散機率#

本節目標#

  • 認識樣本空間、事件與古典機率的定義
  • 用組合數(連結 7.2 的 binomial)計算古典機率
  • 理解條件機率與 Bayes 定理,並以疾病篩檢例題手算對照
  • 判斷兩事件是否獨立
  • 實驗:用 SymPy 分析 Monty Hall 問題的三門機率

樣本空間與事件#

樣本空間(sample space) \(S\) 是隨機實驗所有可能結果的集合;事件(event)是樣本空間的子集合。例如擲一顆骰子:

\[ S = \{1, 2, 3, 4, 5, 6\} \]

「擲出偶數」是事件 \(A = \{2, 4, 6\} \subseteq S\) 。用 Python 的集合可以直接表示:

S = {1, 2, 3, 4, 5, 6}
A = {2, 4, 6}          # 事件:擲出偶數
B = {1, 2, 3}          # 事件:擲出不超過 3

print(A | B)   # 聯集 A ∪ B = {1, 2, 3, 4, 6}
print(A & B)   # 交集 A ∩ B = {2}
print(A - B)   # 差集 A - B = {4, 6}

古典機率與組合數#

當每個結果發生的機會均等(古典機率模型),事件 \(A\) 的機率為

\[ P(A) = \frac{|A|}{|S|} = \frac{\text{有利結果數}}{\text{總結果數}} \]

許多問題的關鍵在於「數結果」,這正是第 7.2 節組合數 \(C(n, k) = \binom{n}{k}\) 的用武之地。

例題:從 52 張撲克牌中抽 5 張,求恰好 3 張紅心的機率。

from sympy import binomial, Rational

favorable = binomial(13, 3) * binomial(39, 2)  # 3 張紅心 + 2 張非紅心
total = binomial(52, 5)

P = Rational(favorable, total)
print(favorable)                      # 211926
print(total)                          # 2598960
print(P)                              # 2717/33320
print(P.evalf(4))                     # 0.008153

例題:袋子有 5 紅球、3 白球,任取 2 球,求「恰一紅一白」的機率。

from sympy import binomial, Rational

P = Rational(binomial(5, 1) * binomial(3, 1), binomial(8, 2))
print(P)        # 15/28

條件機率#

在已知事件 \(B\) 發生的前提下,事件 \(A\) 發生的機率稱為條件機率:

\[ P(A \mid B) = \frac{P(A \cap B)}{P(B)} \quad (P(B) > 0) \]

條件機率的直覺:把樣本空間縮小成 \(B\) ,只在 \(B\) 的世界裡重新計算比例。

例題:擲兩顆骰子,已知點數和為 8,求其中一顆是 6 的機率。

from sympy import Rational

S = {(i, j) for i in range(1, 7) for j in range(1, 7)}
B = {p for p in S if p[0] + p[1] == 8}       # 條件事件:和為 8
A = {p for p in B if 6 in p}                 # 和為 8 且有一顆是 6

print(len(B))                        # 5
print(len(A))                        # 2
print(Rational(len(A), len(B)))      # 2/5

Bayes 定理:疾病篩檢例題#

由條件機率定義可推出 Bayes 定理:

\[ P(A \mid B) = \frac{P(B \mid A)\, P(A)}{P(B)} \]

經典例題:某疾病盛行率為 \(1\%\) ( \(P(D) = 0.01\) )。篩檢的敏感度為 \(99\%\) (患病者驗出陽性的機率 \(P(+ \mid D) = 0.99\) ),偽陽性率為 \(5\%\) (健康者驗出陽性的機率 \(P(+ \mid D^c) = 0.05\) )。某人篩檢呈陽性,他真正患病的機率是多少?

先手算:由全機率公式,

\[ P(+) = P(+ \mid D)P(D) + P(+ \mid D^c)P(D^c) = 0.99 \times 0.01 + 0.05 \times 0.99 = 0.0594 \]

再由 Bayes 定理:

\[ P(D \mid +) = \frac{0.99 \times 0.01}{0.0594} \approx 0.1667 \]

答案是約 16.7%,遠低於直覺預期!用 SymPy 驗證:

from sympy import Rational

P_D      = Rational(1, 100)     # 盛行率
P_pos_D  = Rational(99, 100)    # 敏感度
P_pos_nD = Rational(5, 100)     # 偽陽性率

P_pos = P_pos_D * P_D + P_pos_nD * (1 - P_D)   # 全機率公式
P_D_pos = P_pos_D * P_D / P_pos                # Bayes 定理

print(P_pos)      # 99/1667 ≈ 0.0594
print(P_D_pos)    # 11/66 ≈ 0.1667
print(P_D_pos.evalf(4))   # 0.1667

這說明了為什麼低盛行率疾病的大規模篩檢需要複檢:陽性結果中大多是偽陽性。

獨立性#

若 \(P(A \cap B) = P(A)\, P(B)\) ,則稱事件 \(A\) 與 \(B\) 獨立。等價說法: \(B\) 的發生不影響 \(A\) 的機率,即 \(P(A \mid B) = P(A)\) 。

from sympy import Rational

# 擲一顆骰子
S = {1, 2, 3, 4, 5, 6}
P = lambda E: Rational(len(E), len(S))

A = {2, 4, 6}    # 偶數
B = {1, 2, 3}    # 不超過 3

left  = P(A & B)        # P(A ∩ B) = 1/6
right = P(A) * P(B)     # P(A)·P(B) = 1/2 · 1/2 = 1/4

print(left, right, left == right)   # 1/6 1/4 False → 不獨立

注意:互斥( \(A \cap B = \emptyset\) )與獨立是不同的概念。互斥事件的機率可以相加,但除非其中一方機率為 0,互斥事件不可能獨立。

動手實驗:Monty Hall 三門問題#

遊戲規則:三扇門後恰有一扇有汽車,另兩扇是山羊。你先選一扇門,主持人(知道答案)打開另一扇有山羊的門,並問你要不要換到剩下的那扇門。換門比較有利嗎?

直接列舉樣本空間(汽車位置 × 你的初選 × 主持人開哪扇門),但要正確加權:主持人面對兩扇山羊門時是隨機選一扇,所以「車=初選」的情況各有兩種主持人選擇、每種機率 \(1/18\) ;「車≠初選」時主持人別無選擇、機率 \(1/9\) :

from sympy import Rational

doors = {1, 2, 3}
cases = []   # (汽車位置, 初選, 主持人開的門, 機率)

for car in doors:
    for pick in doors:
        goat_doors = doors - {car, pick}
        for opened in goat_doors:
            if car == pick:
                w = Rational(1, 18)   # 主持人有 2 扇門可選,各 1/3·1/3·1/2
            else:
                w = Rational(1, 9)    # 主持人只有 1 扇可開
            cases.append((car, pick, opened, w))

print("總機率:", sum(w for *_, w in cases))   # 1(權重完備)

stay_win = sum(w for car, pick, _, w in cases if pick == car)
swap_win  = sum(w for car, pick, _, w in cases if pick != car)

print("不換門獲勝機率:", stay_win)    # 1/3
print("換門獲勝機率:  ", swap_win)    # 2/3

再用蒙特卡羅模擬(Python 的 random)驗證:

import random

N = 100_000
swap_wins = 0
for _ in range(N):
    car = random.randrange(3)
    pick = random.randrange(3)
    # 主持人開一扇既非車也非初選的門;換到剩下的那扇
    options = [d for d in range(3) if d != pick and d != car]
    opened = random.choice(options)
    new_pick = [d for d in range(3) if d != pick and d != opened][0]
    if new_pick == car:
        swap_wins += 1

print(f"模擬換門獲勝頻率 ≈ {swap_wins / N:.4f}")   # ≈ 0.6667

模擬結果約為 \(2/3\) ,與理論一致:**換門的獲勝機率是 \(2/3\) ,不換只有 \(1/3\) **。關鍵在於主持人的行為不是隨機的——他一定開山羊門,這帶給了你額外的資訊。

試著修改實驗:

  1. 若主持人隨機開一扇門(可能開到汽車,遊戲提前結束),只統計遊戲進行到底的情況,換門還有優勢嗎?
  2. 把門數改成 100 扇、主持人開 98 扇山羊門,換門的獲勝機率變成多少?
  3. 用 8.2 節將學到的 sympy.stats 重新表示 Monty Hall,計算期望值。

小結與練習#

  • 樣本空間是所有結果的集合,事件是其子集合;古典機率 \(P(A) = |A| / |S|\)
  • 組合數 \(\binom{n}{k}\) 是數結果的核心工具(連結 7.2)
  • 條件機率 \(P(A \mid B) = P(A \cap B) / P(B)\) ;Bayes 定理把 \(P(A \mid B)\) 與 \(P(B \mid A)\) 互換
  • 疾病篩檢例題顯示:低盛行率下陽性結果不必然代表高患病機率
  • 獨立的定義是 \(P(A \cap B) = P(A) P(B)\) ,與互斥不同
  • Monty Hall:換門獲勝機率 \(2/3\)

練習

  1. 擲三顆公平骰子,求點數和為 10 的機率(用列舉法與生成函數兩種方式)。
  2. 從 52 張牌抽 5 張,求「同花順」的機率。
  3. 兩個盒子:甲盒有 3 紅 2 白球,乙盒有 1 紅 4 白球。隨機選一盒再抽一球,結果是紅球。求此球來自甲盒的機率(Bayes 定理)。
  4. 證明:若 \(A\) 與 \(B\) 互斥且 \(P(A), P(B) > 0\) ,則 \(A\) 與 \(B\) 不獨立。
  5. 修改 Monty Hall 模擬程式,讓主持人隨機開門,驗證換門優勢消失(在遊戲完整進行的條件下變成 \(1/2\) )。