この章で学ぶこと:AIの「罰」の正体
第5章から第9章まで、分類のモデルを学習させるときに、交差エントロピー という罰(損失)を使ってきました。「正解に付けた確率が半分になるたびに、罰が約0.69ずつ増える」という性質だけで使ってきましたが、この0.69がどこから来たのか、なぜこの罰を使うのかは、まだ説明していません。
この章では、その正体を、確率・統計・情報理論 という数学から説明します。公式を覚えるのではなく、Pythonでサイコロや硬貨を何万回も振って確かめてから、式で表します。
確率変数:結果が偶然で決まる数
サイコロを1回振ると、1〜6のどれかの目が出ます。どの目が出るかは振ってみるまで分かりませんが、どの目も同じくらい出やすく、それぞれ 61 の確率で出ます。
このように、「偶然で値が決まる数」を 確率変数 と呼び、X のような大文字で書きます。そして、「X が6になる確率」を P(X=6)=61 のように書きます(P は確率を表す英語 probability の頭文字)。
確率は0から1の間の数で、すべての場合の確率を足すと1 になります。
実験:サイコロを10万回振る
Pythonでサイコロを10万回振り、それまでに出た目の平均と、6が出た割合を記録しました。
サイコロを振った回数(横軸、1000回まで)と、それまでに出た目の平均(縦軸)。最初の10回ほどは6から2.6まで大きく上下し、その後は3.3〜3.8の間に収まる。1000回の時点で3.60で、3.5に近づきつつあるが、まだ少し上にある
振った回数が少ないうちは、平均は大きくぶれます(最初の1回は6が出たので、平均は6)。回数を増やすほど、平均は 3.5 に、6が出た割合は 61≈0.167 に近づいていきます。ただし、1000回でもまだ3.60で、近づき方はゆっくりです。
試行の回数を増やすほど、平均が決まった値に近づくことを、大数の法則 と呼びます。では、この3.5という数は、どうやって計算できるのでしょうか。
期待値と分散:確率変数の「平均」と「ばらつき」
期待値:値 × 確率 を、全部足したもの
サイコロの目の平均が近づいていく3.5は、次のように計算できます。それぞれの目に、その目が出る確率を掛けて、全部足します。
1×61+2×61+3×61+4×61+5×61+6×61=621=3.5
これを確率変数 X の 期待値 と呼び、E[X] と書きます(E は期待値を表す英語 expectation の頭文字)。第4章の ∑ を使うと、次のように書けます。
E[X]=x∑x×P(X=x)
「X が取りうるすべての値 x について、x×P(X=x) を足す」という意味です。
期待値は「何回も繰り返したときの平均」です。1回で出る値ではありません(サイコロで3.5の目は出ません)。
例:くじの期待値
1000本のくじのうち、1万円が1本、1000円が10本、残りははずれ(0円)です。1本引いたときにもらえる金額の期待値は、次のとおりです。
10000×10001+1000×100010+0×1000989=10+10+0=20円
このくじが1本300円で売られていたら、何回も買うと、平均して1本あたり280円損をすることになります。
分散:期待値からのずれの2乗の、期待値
第3章では、データのばらつきを 分散(平均からの差の2乗の平均)で表しました。確率変数でも同じように、「期待値からのずれの2乗」の期待値を分散と呼び、V[X] と書きます。
V[X]=x∑(x−E[X])2×P(X=x)
サイコロなら、期待値3.5からのずれの2乗は、目が1〜6のとき 6.25,2.25,0.25,0.25,2.25,6.25 です。それぞれに 61 を掛けて足すと、次のようになります。
V[X]=66.25+2.25+0.25+0.25+2.25+6.25=617.5≈2.917
標準偏差は、その平方根で 2.917≈1.708 です。サイコロの目は、期待値3.5からだいたい1.7くらい離れた値が出る、という目安になります。
機械学習のどこで使うか
学習の罰(損失)は、「訓練データ全体での罰の平均」でした。これは、データを1つ選んだときの罰という確率変数の、期待値を求めていることになります。第8章のミニバッチも、「一部のデータの平均で、全体の期待値の見当をつける」という考え方です。
Pythonで確かめる、よくある誤解と振り返り
サイコロを振るシミュレーション
import numpy as np
rng = np.random.default_rng(0) # 乱数の種を0に固定(第9章の再現性)
rolls = rng.integers(1, 7, 100000) # 1以上7未満の整数(1〜6)を10万個
print(rolls[:10]) # → [6 4 4 2 2 1 1 1 2 5]
print(rolls.mean()) # → 3.498…(期待値3.5に近い)
print((rolls == 6).mean()) # → 0.165…(1/6 ≈ 0.167 に近い)
rng.integers(1, 7, 個数) は、1以上 7未満 の整数を作ります(7は入りません)。(rolls == 6) は、6のところが True、それ以外が False の配列で、その平均は True の割合になります。
期待値と分散を、式から計算する
values = np.array([1, 2, 3, 4, 5, 6]) # 取りうる値
probs = np.full(6, 1 / 6) # それぞれの確率(6個とも 1/6)
mean = (values * probs).sum() # 期待値: 値 × 確率 の合計 → 3.5
var = ((values - mean) ** 2 * probs).sum() # 分散 → 2.916…
print(mean, var, np.sqrt(var)) # 標準偏差 → 1.707…
NumPy の配列どうしの * は、同じ位置の数どうしの掛け算です(第3章)。スライドの ∑ の式を、そのまま1行で書けます。
よくある誤解
- 「6が5回続けて出なかったから、次は6が出やすい」: サイコロには記憶がないので、次に6が出る確率は、いつでも 61 です。「そろそろ出るはず」と考える誤りは、ギャンブラーの誤謬 と呼ばれます
- 「大数の法則があるので、10回振れば平均はほぼ3.5になる」: 実験では、10回の平均は2.8でした。平均が期待値に近づくには、たくさんの回数が必要です
- 「期待値は、一番出やすい値」: くじの期待値は20円ですが、20円が当たることはありません。一番出やすいのは0円(はずれ)です
振り返り
- 偶然で値が決まる数を確率変数と呼ぶ。すべての場合の確率を足すと1になる
- 期待値 E[X] は「値 × 確率」の合計で、何回も繰り返したときの平均。大数の法則により、実際の平均は期待値に近づく
- 分散 V[X] は「期待値からのずれの2乗」の期待値で、ばらつきの大きさを表す