iPAS AI 應用規劃師 中級 科目三 機器學習技術與應用

Monte Carlo 怎麼算條件機率 P(A|B)?

原題 41

考慮擲出骰子並採用 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)?

點選你的答案。

01 總結

一句話總結

條件機率 P(A|B) 的公式是 P(A∩B) / P(B),換成程式碼就是 A_and_B.sum() / B.sum():分子是「A 和 B 同時發生」的次數,分母是「B 發生」的次數

02 情境

先感受問題:「已知骰子大於 3,偶數機率是多少?」

假設你在桌遊社裡用程式幫大家驗證機率。你擲了 10 萬次骰子,現在有人問:「如果你知道這次骰出來的點數大於 3,那麼它同時是偶數的機率是多少?」

大於 3 的點數有 4、5、6 三種,其中偶數只有 4 和 6 兩種,所以直覺告訴你答案應該接近 2/3 ≈ 0.667。

這就是「條件機率」的核心想法:縮小範圍。不是在所有 10 萬次中找偶數,而是先把範圍縮小到「大於 3 的那些次」,再看其中有多少是偶數。

用程式碼來表達這個縮小範圍的概念,分母就是 B 的次數(大於 3 發生了幾次),分子是 A 和 B 同時滿足的次數(又大於 3 又是偶數)。

03 對照

直接算「偶數的總次數」,為什麼會算錯?

  1. 沒縮小範圍就算:如果用 A.sum() / n 算出的是「所有 10 萬次中偶數的機率」,也就是無條件機率 P(A) ≈ 0.5,完全沒有用到「已知大於 3」這個條件。
  2. 用 A.sum() 當分母:選項 C 的 A_and_B.sum() / A.sum() 算的是「在偶數中有多少大於 3」,這是 P(B|A),不是 P(A|B),把條件搞反了。
  3. 用兩個事件的次數相乘當分母:選項 A 的 A.sum() * B.sum() 沒有機率學上的意義,不對應任何正確公式。
  4. 用兩個事件的次數相加當分母:選項 B 的 A.sum() + B.sum() 也沒有意義,不是條件機率的計算方式,這樣分母會超過總樣本數。
  5. 混淆聯合機率與條件機率:聯合機率 P(A∩B) = A_and_B.sum() / n,是兩者同時發生的無條件機率;條件機率 P(A|B) 要再除以 P(B),也就是再縮小到 B 的範圍。
04 解法

條件機率:先鎖定 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 程式碼對照

中級考試大概率會考程式碼跟公式,所以這部分你還是要學。但如果現在學起來很痛苦,可以先跳過,等讀完其他題目回頭再來。

Step 1 純故事版(不出現公式)

想像你是籃球場的計分員,負責記錄每次投籃。你有一本記錄簿,裡面有「是否三分球」和「是否進球」兩欄。

有人問:「已知這次是三分球,進球的機率是多少?」

你不會去數所有投籃的進球率,而是先翻到「三分球」那幾頁,再數其中進球了幾次。這就是條件機率:先縮小到已知的條件範圍,再計算目標事件的比例。

Monte Carlo 做的事情一樣:先用程式模擬大量樣本,然後數出「符合條件 B 的樣本」有多少,再數其中「同時符合 A」的有多少,兩者相除就是 P(A|B) 的估計值。

Step 2 中文 ↔ 程式碼對照
白話說法程式碼
模擬 10 萬次骰子dice_rolls = np.random.randint(1, 7, size=n)
事件 A:擲出偶數A = (dice_rolls % 2 == 0)
事件 B:擲出大於 3B = (dice_rolls > 3)
A 和 B 同時發生A_and_B = A & B
P(A|B) = P(A∩B) / P(B)A_and_B.sum() / B.sum()
Step 3 符號角色表
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 越大估計越準確
Step 4 完整公式對應
條件機率公式: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),條件反了
Step 5 自我複述
  1. P(A|B) 和 P(B|A) 有什麼差異?請各舉一個生活例子。
  2. 如果把程式碼的 B.sum() 改成 n,算出的是什麼機率?
  3. 為什麼選項 C 算出來的數字和正解 D 接近(都約 0.667),但意義完全不同?
  4. Monte Carlo 的估計值和理論值為什麼不會完全相同?n 增大時會怎樣?
  5. np.random.seed(123) 的作用是什麼?去掉會怎樣?
05 陷阱

為什麼其他選項是錯的

選項 A A_and_B.sum() / (A.sum() * B.sum())

字面在說什麼:用 A 發生次數乘以 B 發生次數當分母。

為什麼不對:A.sum() 和 B.sum() 各約 50,000,相乘後分母高達 25 億,讓結果趨近於零。這個算式在機率學中沒有意義,不對應任何已知的機率概念。這是把「積事件」和「積」混淆:A∩B 的個數除以 A 個數,而非除以 A 個數乘以 B 個數。

誰會選錯:看到題目裡同時有 A 和 B,不假思索地把兩者都放進分母、卻用乘法而非加法的人。直覺上覺得「兩個事件的組合」就要用兩個的乘積。

選項 B A_and_B.sum() / (A.sum() + B.sum())

字面在說什麼:用 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,於是選了「兩者相加」這個看起來最保險的選項。

選項 C A_and_B.sum() / A.sum()

字面在說什麼:用 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)),以為選了正確公式,實際上公式是顛倒的。

06 變形

同個考點下次怎麼變形

變形 1 公式換場景

直覺:醫療篩檢中,已知某人測試陽性,實際上有病的機率要怎麼算?

答案:用條件機率 P(有病|陽性) = P(有病∩陽性) / P(陽性)。同樣的公式,分子是「真陽性」次數,分母是「所有陽性」次數,這就是醫學上的「陽性預測值(PPV)」。

變形 2 反向條件

直覺:同一個骰子程式,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) 就不會相等。

變形 3 獨立事件

直覺:如果事件 A 和 B 互相獨立,P(A|B) 等於什麼?

答案:P(A|B) = P(A)。獨立的意思就是「B 的發生不影響 A 的機率」。可以用程式驗證:如果把 B 改成「擲出奇數或偶數」(必然事件),P(A|B) 就等於 P(A) = 0.5。

變形 4 增加樣本數

直覺:把 n 從 100,000 改成 1,000,估計結果會怎麼變化?

答案:隨機誤差會增大,估計值在 0.667 附近波動更大。Monte Carlo 的收斂速度是 1/√n,樣本數減少 100 倍,誤差增加 10 倍。這就是為什麼 Monte Carlo 模擬通常需要大量樣本才能得到可靠估計。

變形 5 程式碼變體

直覺:如果改寫成 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 的寫法,但背後邏輯相同。

07 延伸

想再往下看,這 5 個

出處

iPAS 經濟部產業人才能力鑑定 ・ 114 年第二梯次 iPAS AI 應用規劃師 中級 科目三 機器學習技術與應用 第 41 題

查看官方原文 PDF