Day 020 — 確率の基礎(確率とは何か・頻度主義 vs ベイズ主義)

2026-04-29 白 / Phase 1 理論 確率の基礎

📚 背景知識(読んでから問題へ)

「確率」って何だろう?

確率(probability)とは、「ある出来事が起こりやすさの度合い」を0〜1の数値で表したもの。

  • 0 = 絶対に起こらない
  • 1 = 必ず起こる
  • 0.5 = 2回に1回くらい起こる(コインの表が出る確率)

2つの確率の考え方

① 頻度主義(Frequentist)

「コインを100万回投げたとき、表が出た割合」で確率を定義する考え方。

  • 得意: 実験で繰り返し観測できる現象(サイコロ・コインなど)
  • 苦手: 「明日雨が降る確率」のような1度きりの出来事

② ベイズ主義(Bayesian)

「自分が持っている信念(事前確率)を、新しい証拠で更新していく」考え方。

  • : 「この患者は病気だ」という確率を、検査結果を見るたびに更新する
  • Kaggleで重要: データが少ないとき・事前知識を活用したいとき

確率の基本ルール

ルール説明
和事象AまたはBが起こる確率P(A ∪ B) = P(A) + P(B) - P(A ∩ B)
積事象(独立)AとBが両方起こる確率(互いに無関係)P(A ∩ B) = P(A) × P(B)
余事象Aが起こらない確率P(Aの余) = 1 - P(A)

直感的な例え:

  • 「明日雨が降る OR 曇りになる確率」= 雨の確率 + 曇りの確率 - 雨かつ曇りの確率(同時ありなら引く)
  • 「サイコロを2回振って両方6が出る確率」= (1/6) × (1/6) = 1/36(独立だから掛け算)

📝 問題

Part 1: 基礎概念(記述式)

次の問いに日本語または短いコードで答えよ。

Q1: サイコロを1回振ったとき、偶数が出る確率を求めよ。

Q2: コインを3回投げて「すべて表」になる確率を求めよ。

Q3: トランプ52枚からランダムに1枚引いたとき、「ハートまたは絵札(J・Q・K)」が出る確率を求めよ。(ハート:13枚、絵札:12枚、ハートの絵札:3枚)


Part 2: Python で確率をシミュレーション(コーディング)

以下のコードを完成させて、「コインを10,000回投げたときの表の出現率」をシミュレートせよ。

import numpy as np

np.random.seed(42)  # 再現性のため

# コインを N 回投げるシミュレーション
N = 10000

# 0 = 裏、1 = 表 でランダムに N 個生成
throws = np.random.randint(___,  ___, size=N)  # ← 空欄を埋める

# 表(1)の出現率を計算
heads_rate = ___  # ← 空欄を埋める

print(f"表の出現率: {heads_rate:.4f}")
print(f"理論値 0.5 との差: {abs(heads_rate - 0.5):.4f}")

期待される出力の例:

▶ 出力を見る
表の出現率: 0.4983
理論値 0.5 との差: 0.0017

Part 3: 確率の直感クイズ

次の問いに対して、直感で答えてから実際に計算せよ。

Q4(直感クイズ): クラスに23人います。「2人以上が同じ誕生日を持つ確率」はどのくらいだと思うか?

(①: 10%以下 / ②: 50%前後 / ③: 90%以上)

実際に計算してみると、答えは約50.7%。これを「誕生日問題(Birthday Problem)」という。なぜそんなに高いのか説明せよ。


🔍 ヒント(段階的開示)

ヒント1(方向性)

Part 2 の np.random.randint(0, 2, size=N) は「0か1をランダムにN個生成する」コード。

heads_rate は 1 の個数 ÷ 総回数 = 表が出た割合。

ヒント2(アプローチ)
  • Q3: 「ハートまたは絵札」= ハートの枚数 + 絵札の枚数 - 重複(ハートの絵札)
  • 誕生日問題: 「誰とも誕生日がかぶらない確率」の余事象で考える
ヒント3(コード骨格)
# Part 2 の解答
throws = np.random.randint(0, 2, size=N)  # 0か1をN個生成
heads_rate = throws.mean()  # 1の割合 = 平均値(0か1だから)

# 誕生日問題(参考コード)
prob_no_match = 1.0
for i in range(23):
    prob_no_match *= (365 - i) / 365
prob_match = 1 - prob_no_match
print(f"23人でかぶる確率: {prob_match:.3f}")

模範解答

Part 1 の解答

Q1: 偶数は {2, 4, 6} の3通り → 3/6 = 0.5(50%)

Q2: コインは独立なので掛け算 → (1/2)³ = 1/8 = 0.125(12.5%)

Q3: P(ハートまたは絵札) = P(ハート) + P(絵札) - P(ハートの絵札)

= 13/52 + 12/52 - 3/52 = 22/52 ≈ 0.423(42.3%)

Part 2 の解答

import numpy as np

np.random.seed(42)
N = 10000

throws = np.random.randint(0, 2, size=N)  # 0=裏, 1=表
heads_rate = throws.mean()               # 1の割合 = 平均

print(f"表の出現率: {heads_rate:.4f}")
print(f"理論値 0.5 との差: {abs(heads_rate - 0.5):.4f}")

Part 3 の解答(誕生日問題)

# 誕生日問題:23人のうち少なくとも2人が同じ誕生日の確率
prob_no_match = 1.0
for i in range(23):
    prob_no_match *= (365 - i) / 365

prob_at_least_one_match = 1 - prob_no_match
print(f"23人でかぶる確率: {prob_at_least_one_match:.3f}")  # → 0.507

答え: ③ 50%前後(正確には50.7%)


🪜 Step-by-Step 解説

1
確率の基本計算(Q1〜Q3)
  • Q1: 全体の数(6)に対して条件を満たす数(3)の割合 → 3÷6=0.5
  • Q2: 独立な事象は掛け算。1回表の確率は1/2、3回連続なら (1/2)×(1/2)×(1/2)
  • Q3: 「AまたはB」の確率は足し算、ただし両方当てはまる部分を引く(ダブルカウント防止)
2
NumPy でシミュレーション
throws = np.random.randint(0, 2, size=N)
  • np.random.randint(0, 2): 0 以上 2 未満の整数 = {0, 1} をランダムに生成
  • size=N: N 個生成する
  • throws.mean(): 0と1だけのリストの平均 = 1の割合 = 表の出現率
3
誕生日問題の直感

「23人のうち誰もかぶらない確率」を計算し、それを 1 から引く(余事象)。

1人目は任意の誕生日(365/365)

2人目は1人目と違う日(364/365)

3人目は2人と違う日(363/365)...

23人全員かぶらない確率 = 365/365 × 364/365 × ... × 343/365 ≈ 49.3%

→ かぶる確率 = 1 - 0.493 ≈ 50.7%

意外に高い理由: 「自分vs誰か」ではなく「全23人の組み合わせ(=253通り)」をチェックしているから。


📐 数学・統計の補足(文系向け)

「確率の掛け算」って何で掛けるの?

コインを2回投げる場合:

  • 全部の組み合わせ: (表,表) / (表,裏) / (裏,表) / (裏,裏) = 4通り
  • 両方表 = 1通り → 確率 = 1/4

これを「1/2 × 1/2 = 1/4」とも書ける。

独立なら「両方起こる確率 = それぞれの確率を掛け算」 が成り立つ。

余事象の考え方

「少なくとも1回表が出る確率」を直接計算するのは複雑(全部裏 + 1回表 + 2回表...)。

「全部裏になる確率(= 余事象)を引く」方が楽。

1 - (1/2)³ = 1 - 1/8 = 7/8 = 87.5%


🏆 Kaggleでの実践的な使い方

  1. 欠損値の補完: 欠損していないデータの分布(確率分布)を推定して補完する
  2. クラス不均衡の理解: 「正例が5%しかない」= クラスの出現確率が偏っている
  3. 予測結果の解釈: モデルの出力 predict_proba() は確率値(0〜1)を返す
  4. ベイズ最適化(Optuna等): 「このハイパーパラメータが良さそうな確率」を更新しながら探索

⚠️ よくある誤解・ミス

誤解・ミスなぜ起こるか正しい理解
「コインが10回連続で表 → 次は裏が出やすい」ギャンブラーの誤謬コインの各回は独立。過去の結果は次に影響しない
P(AまたはB) = P(A) + P(B) と計算してしまう重複を考えない重複分(P(A ∩ B))を引く必要がある
np.random.randint(0, 2) で「2が出ることがある」と思う範囲の勘違いrandint(a, b) は a 以上 b 未満 → 0か1のみ

🚀 次のステップ

  • 発展: 「コインを10000回投げるシミュレーションを複数回繰り返してヒストグラムを描く」(大数の法則の可視化)
  • 次回予告: 条件付き確率・ベイズの定理(「検査で陽性 → 実際に病気の確率は?」)

🎯 自己評価

自分の回答

気づき・メモ