Monte Carlo 怎麼算條件機率 P(A|B)?
考慮擲出骰子並採用 Monte Carlo 方法估算條件機率,參考附圖程式碼。
import numpy as np
np.random.seed(123)
n = 100000
dice_rolls = np.random.randint(1, 7, size=n)
A = (dice_rolls % 2 == 0)
B = (dice_rolls > 3)
A_and_B = A & B
事件 A:擲出偶數
事件 B:擲出大於 3
請問下列何者為條件機率 P(A | B) 的正確值?
程式模擬了 10 萬次擲骰子,定義了兩個事件:事件 A 是擲出偶數(2、4、6),事件 B 是擲出大於 3 的點數(4、5、6)。程式分別算出 A 出現幾次、B 出現幾次,以及 A 和 B 同時出現幾次,接著提供四個不同的計算式。
問你:哪一個計算式才能正確算出「已知 B 發生的前提下,A 發生的機率」P(A|B)?
一句話總結
條件機率 P(A|B) 的公式是 P(A∩B) / P(B),換成程式碼就是 A_and_B.sum() / B.sum():分子是「A 和 B 同時發生」的次數,分母是「B 發生」的次數。
先感受問題:「已知骰子大於 3,偶數機率是多少?」
假設你在桌遊社裡用程式幫大家驗證機率。你擲了 10 萬次骰子,現在有人問:「如果你知道這次骰出來的點數大於 3,那麼它同時是偶數的機率是多少?」
大於 3 的點數有 4、5、6 三種,其中偶數只有 4 和 6 兩種,所以直覺告訴你答案應該接近 2/3 ≈ 0.667。
這就是「條件機率」的核心想法:縮小範圍。不是在所有 10 萬次中找偶數,而是先把範圍縮小到「大於 3 的那些次」,再看其中有多少是偶數。
用程式碼來表達這個縮小範圍的概念,分母就是 B 的次數(大於 3 發生了幾次),分子是 A 和 B 同時滿足的次數(又大於 3 又是偶數)。
直接算「偶數的總次數」,為什麼會算錯?
- 沒縮小範圍就算:如果用 A.sum() / n 算出的是「所有 10 萬次中偶數的機率」,也就是無條件機率 P(A) ≈ 0.5,完全沒有用到「已知大於 3」這個條件。
- 用 A.sum() 當分母:選項 C 的 A_and_B.sum() / A.sum() 算的是「在偶數中有多少大於 3」,這是 P(B|A),不是 P(A|B),把條件搞反了。
- 用兩個事件的次數相乘當分母:選項 A 的 A.sum() * B.sum() 沒有機率學上的意義,不對應任何正確公式。
- 用兩個事件的次數相加當分母:選項 B 的 A.sum() + B.sum() 也沒有意義,不是條件機率的計算方式,這樣分母會超過總樣本數。
- 混淆聯合機率與條件機率:聯合機率 P(A∩B) = A_and_B.sum() / n,是兩者同時發生的無條件機率;條件機率 P(A|B) 要再除以 P(B),也就是再縮小到 B 的範圍。
條件機率:先鎖定 B 的範圍,再數 A
骰子模擬的結果:10 萬次中,大於 3 的次數(B)大約是 50,000 次(機率 3/6 = 0.5),其中又是偶數的(A∩B,即點數 4 或 6)大約是 33,333 次(機率 2/6 ≈ 0.333)。
條件機率公式:P(A|B) = P(A∩B) / P(B)
換成樣本次數:P(A|B) ≈ A_and_B.sum() / B.sum() ≈ 33,333 / 50,000 ≈ 0.667
這與直覺計算(大於 3 的 3 個點數 4、5、6 中,偶數有 4 和 6 共 2 個,所以 2/3)完全一致。
這就是選項 D 講的:A_and_B.sum() / B.sum()。
技術版:條件機率公式與 Monte Carlo 程式碼對照
中級考試大概率會考程式碼跟公式,所以這部分你還是要學。但如果現在學起來很痛苦,可以先跳過,等讀完其他題目回頭再來。
想像你是籃球場的計分員,負責記錄每次投籃。你有一本記錄簿,裡面有「是否三分球」和「是否進球」兩欄。
有人問:「已知這次是三分球,進球的機率是多少?」
你不會去數所有投籃的進球率,而是先翻到「三分球」那幾頁,再數其中進球了幾次。這就是條件機率:先縮小到已知的條件範圍,再計算目標事件的比例。
Monte Carlo 做的事情一樣:先用程式模擬大量樣本,然後數出「符合條件 B 的樣本」有多少,再數其中「同時符合 A」的有多少,兩者相除就是 P(A|B) 的估計值。
| 白話說法 | 程式碼 |
|---|---|
| 模擬 10 萬次骰子 | dice_rolls = np.random.randint(1, 7, size=n) |
| 事件 A:擲出偶數 | A = (dice_rolls % 2 == 0) |
| 事件 B:擲出大於 3 | B = (dice_rolls > 3) |
| A 和 B 同時發生 | A_and_B = A & B |
| P(A|B) = P(A∩B) / P(B) | A_and_B.sum() / B.sum() |
- P(A|B)
- 條件機率:在 B 已發生的前提下,A 發生的機率
- P(A∩B)
- 聯合機率:A 和 B 同時發生的機率
- P(B)
- 邊際機率(marginal probability):B 發生的機率,不論 A
- A_and_B.sum()
- A 和 B 同時為 True 的樣本數,近似 n×P(A∩B)
- B.sum()
- B 為 True 的樣本數,近似 n×P(B)
- n
- 總模擬次數(10 萬),n 越大估計越準確
條件機率公式:P(A|B) = P(A∩B) / P(B) 骰子理論值: P(A) = 3/6 = 0.5 (偶數:2, 4, 6) P(B) = 3/6 = 0.5 (大於3:4, 5, 6) P(A∩B) = 2/6 ≈ 0.333 (偶數且大於3:4, 6) P(A|B) = (2/6) / (3/6) = 2/3 ≈ 0.667 程式碼估計(10萬次模擬): A_and_B.sum() ≈ 33,333 B.sum() ≈ 50,000 P(A|B) ≈ 33,333 / 50,000 ≈ 0.667 ✓ 與理論值吻合 選項 A:A_and_B.sum() / (A.sum() * B.sum()) 分母 ≈ 50,000 × 50,000 = 2.5 × 10⁹ → 結果接近 0,無意義 選項 B:A_and_B.sum() / (A.sum() + B.sum()) 分母 ≈ 100,000 → 實際算的是 P(A∩B),不是條件機率 選項 C:A_and_B.sum() / A.sum() ≈ 33,333 / 50,000 ≈ 0.667 → 這是 P(B|A),條件反了
- P(A|B) 和 P(B|A) 有什麼差異?請各舉一個生活例子。
- 如果把程式碼的 B.sum() 改成 n,算出的是什麼機率?
- 為什麼選項 C 算出來的數字和正解 D 接近(都約 0.667),但意義完全不同?
- Monte Carlo 的估計值和理論值為什麼不會完全相同?n 增大時會怎樣?
- np.random.seed(123) 的作用是什麼?去掉會怎樣?
為什麼其他選項是錯的
字面在說什麼:用 A 發生次數乘以 B 發生次數當分母。
為什麼不對:A.sum() 和 B.sum() 各約 50,000,相乘後分母高達 25 億,讓結果趨近於零。這個算式在機率學中沒有意義,不對應任何已知的機率概念。這是把「積事件」和「積」混淆:A∩B 的個數除以 A 個數,而非除以 A 個數乘以 B 個數。
誰會選錯:看到題目裡同時有 A 和 B,不假思索地把兩者都放進分母、卻用乘法而非加法的人。直覺上覺得「兩個事件的組合」就要用兩個的乘積。
字面在說什麼:用 A 發生次數加上 B 發生次數當分母。
為什麼不對:A.sum() + B.sum() ≈ 50,000 + 50,000 = 100,000,接近總樣本數 n,所以這個式子算出來的值近似 A_and_B.sum() / n,也就是聯合機率 P(A∩B),不是條件機率 P(A|B)。條件機率需要「縮小到 B 的範圍」,分母應該只用 B 的次數。
誰會選錯:記得「條件機率要用到 A 和 B」,但不確定分母是相加還是只用 B,於是選了「兩者相加」這個看起來最保險的選項。
字面在說什麼:用 A 的發生次數當分母,A 和 B 同時發生的次數當分子。
為什麼不對:這個式子算的是 P(B|A),也就是「已知擲出偶數,點數大於 3 的機率」,把條件搞反了。骰子的 P(B|A) = P(A∩B) / P(A) = (2/6) / (3/6) = 2/3,確實也約等於 0.667,和正解相同——這是個典型的陷阱,數字一樣但公式意義相反。
誰會選錯:沒注意到 P(A|B) 和 P(B|A) 在這個題目中恰好數值相同(因為 P(A) = P(B)),以為選了正確公式,實際上公式是顛倒的。
同個考點下次怎麼變形
直覺:醫療篩檢中,已知某人測試陽性,實際上有病的機率要怎麼算?
答案:用條件機率 P(有病|陽性) = P(有病∩陽性) / P(陽性)。同樣的公式,分子是「真陽性」次數,分母是「所有陽性」次數,這就是醫學上的「陽性預測值(PPV)」。
直覺:同一個骰子程式,P(B|A) 怎麼算?答案是多少?
答案:P(B|A) = A_and_B.sum() / A.sum(),這就是選項 C 的算法。在這題中 P(B|A) ≈ 33,333 / 50,000 ≈ 0.667,和 P(A|B) 數值相同,但意義完全不同。如果改變骰子面數或改變事件定義,P(A|B) 和 P(B|A) 就不會相等。
直覺:如果事件 A 和 B 互相獨立,P(A|B) 等於什麼?
答案:P(A|B) = P(A)。獨立的意思就是「B 的發生不影響 A 的機率」。可以用程式驗證:如果把 B 改成「擲出奇數或偶數」(必然事件),P(A|B) 就等於 P(A) = 0.5。
直覺:把 n 從 100,000 改成 1,000,估計結果會怎麼變化?
答案:隨機誤差會增大,估計值在 0.667 附近波動更大。Monte Carlo 的收斂速度是 1/√n,樣本數減少 100 倍,誤差增加 10 倍。這就是為什麼 Monte Carlo 模擬通常需要大量樣本才能得到可靠估計。
直覺:如果改寫成 np.mean(A[B]) 而非 A_and_B.sum() / B.sum(),結果一樣嗎?
答案:一樣。A[B] 是 NumPy 的布林索引,取出 B 為 True 時對應的 A 值,np.mean(A[B]) 計算這些 A 值的平均,就是「B 發生時 A 也發生」的比例,等價於條件機率 P(A|B)。這是更 Pythonic 的寫法,但背後邏輯相同。
想再往下看,這 5 個
- 蒙地卡羅方法(Monte Carlo Method)本題核心工具,用大量隨機模擬來估計機率或積分值,樣本越多結果越準確。
- 貝氏定理(Bayes' Theorem)條件機率的進階應用,描述在已有先驗知識的情況下如何更新機率估計。
- 機率分佈(Probability Distribution)描述隨機變數各種結果的機率,骰子模擬的基礎,也是機器學習模型的核心假設。
- 假設檢定(Hypothesis Testing)統計推論的基本方法,條件機率是計算 p-value 的基礎概念。
- 常態分佈(Normal Distribution)Monte Carlo 模擬中最常用的機率分佈之一,許多統計推論都以此為假設基礎。