4.2.5 情報理論の基礎

- 情報量とエントロピーを理解する——不確実性の尺度
- 交差エントロピーを理解する——2つの分布の違いを測る
- KLダイバージェンスを理解する——ある分布から別の分布への「距離」
- Pythonで計算と可視化を行う
数式に入る前に用語をほどく
Section titled “数式に入る前に用語をほどく”情報理論の用語は抽象的に聞こえますが、多くはとても具体的な問いに答えています。
| 用語 | 意味 | 初心者がまず持つとよい問い |
|---|---|---|
bit | log2 を使うときの情報量の単位 | この情報は、はい/いいえの質問いくつ分に相当する? |
nat | 自然対数 ln を使うときの情報量の単位 | 深層学習の損失関数で内部的によく使われる単位 |
log2 | 2 を底とする対数 | 情報量を bit で表したいときに使う |
entropy | 分布の平均的な不確実性 | 答えを見る前に、平均してどれくらい迷っている? |
cross-entropy | 真の分布が P のとき、予測分布 Q を使うコスト | モデルの予測で真実を説明すると、どれくらい高くつく? |
KL divergence | P の代わりに Q を使うことで生じる追加コスト | モデルの分布がずれると、どれくらい余計なコストが増える? |
logits | 確率に変換する前のモデルの生スコア | softmax の前にニューラルネットワークが出す未正規化スコア |
softmax | logits を確率に変換する関数 | クラスごとのスコアを、合計 1 の確率分布に変える |
perplexity | 交差エントロピーが bit 単位のときの 2 ** cross_entropy | 言語モデルの困惑度。低いほど、通常はモデルが迷っていない |
RLHF / PPO | Reinforcement Learning from Human Feedback / Proximal Policy Optimization | KL を使って、微調整後のモデルが元のモデルから離れすぎないようにする訓練手法 |
この節では、情報理論の直感を作るために log2 を使い、単位は bit とします。多くの深層学習ライブラリは自然対数を使うため、損失値の単位は nat です。曲線の形や最適化上の意味は同じで、単位だけが違います。
歴史的背景:この節の情報理論で最も重要な出発点は?
Section titled “歴史的背景:この節の情報理論で最も重要な出発点は?”この節でまず知っておきたい歴史的な出来事は次のとおりです。
| 年 | 論文 | 主要な著者 | 最も重要に解決したこと |
|---|---|---|---|
| 1948 | A Mathematical Theory of Communication | Claude Shannon | 情報量、エントロピー、現代情報理論の主軸を体系的に提示した |
初心者の方がまず覚えておくとよいのは、次の一言です。
シャノンは、「情報がどれくらいあるのか」を初めて厳密に測れるようにした。
なので、この節で出てくる
- 情報量
- エントロピー
- 交差エントロピー
はバラバラな概念ではなく、同じ情報理論の主軸の上にあります。
まず、とても大事な学習の心構え
Section titled “まず、とても大事な学習の心構え”この節で初心者がつまずきやすい点は次の通りです。
- 名前がとても抽象的に見える
- 数式が「数学の中の数学」に見える
でも、ここで本当に大事なのは、最初から定義を全部暗記することではなく、まず次を理解することです。
- なぜ「意外なほど情報量が大きい」のか
- なぜ「不確実なほどエントロピーが大きい」のか
- なぜ分類の損失がこれらと結びつくのか
この節は、まずこんなふうに理解するとよいです。
モデルがどれくらい確信しているか、予測がどれくらい外れているかを、より正確に表すための言葉。
まずは全体の地図を作ろう
Section titled “まずは全体の地図を作ろう”この節は見た目にはあまり「確率の授業」らしく見えませんが、実はモデル学習ととても強く結びついています。

この授業で本当に伝えたいのは、次の点です。
- なぜ「意外な出来事ほど情報量が大きい」のか
- なぜ分布が不確実なほどエントロピーが大きいのか
- なぜ交差エントロピーが分類タスクの中心的な損失関数になるのか
一、情報量 —— 「どれだけ驚くか」
Section titled “一、情報量 —— 「どれだけ驚くか」”あるメッセージが持つ情報量 = それがどれだけ予想外か、です。
- 「太陽は東から昇る」 → 情報量 ≈ 0(まったく意外ではない)
- 「今日の北京は雪が降った」(夏) → 情報量が大きい(とても意外)
- 「今日の北京は雪が降った」(冬) → 情報量は中くらい
起こる確率が低い出来事ほど、起きたときの情報量は大きくなります。
初心者向けのたとえ
Section titled “初心者向けのたとえ”情報量は、まずこんなふうに考えられます。
- 「この出来事にどれくらい驚くか」
たとえば、
- 明日も太陽が昇る → 驚かない
- 夏に雪が降る → かなり驚く
なので、情報量でまず覚えるべきなのは式よりも、次の一文です。
あまり起こらないことほど、起きたときに多くの情報を運ぶ。
数学的な定義
Section titled “数学的な定義”情報量 = -log2(確率)
import numpy as npimport matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']plt.rcParams['axes.unicode_minus'] = False
# 異なる確率に対応する情報量probs = np.linspace(0.01, 1, 100)info = -np.log2(probs)
plt.figure(figsize=(8, 5))plt.plot(probs, info, color='steelblue', linewidth=2)plt.xlabel('事象の確率')plt.ylabel('情報量(bit)')plt.title('情報量 = -log₂(確率)')plt.grid(True, alpha=0.3)
# いくつかの重要な点を注釈for p, label in [(1.0, '必然的な事象'), (0.5, 'コイン投げ'), (0.01, 'まれな事象')]: i = -np.log2(p) plt.annotate(f'{label}\np={p}, info={i:.1f}bit', xy=(p, i), fontsize=10, xytext=(p+0.15, i+0.5), arrowprops=dict(arrowstyle='->', color='gray'))
plt.show()| 事象の確率 | 情報量 | 直感 |
|---|---|---|
| 1.0 | 0 bit | 必ず起こるので、情報はない |
| 0.5 | 1 bit | 1回のコイン投げで1ビットの情報 |
| 0.25 | 2 bit | 2桁の2進数を当てる |
| 0.01 | 6.64 bit | とても意外で、情報量が大きい |
式を直接実行すると、次のようになります。
for p in [1.0, 0.5, 0.25, 0.01]: print(f"p={p:>4}: 情報量={-np.log2(p):.4f} bits")期待される出力:
p= 1.0: 情報量=-0.0000 bitsp= 0.5: 情報量=1.0000 bitsp=0.25: 情報量=2.0000 bitsp=0.01: 情報量=6.6439 bits二、エントロピー —— 平均的な不確実性
Section titled “二、エントロピー —— 平均的な不確実性”エントロピー(Entropy)= ある分布の「平均情報量」= システムの「平均的な不確実性」
エントロピーでまず覚えるべきなのは、定義よりも「混乱の度合い」
Section titled “エントロピーでまず覚えるべきなのは、定義よりも「混乱の度合い」”エントロピーは、まずこんなふうに考えられます。
- 判断する前に、どれくらい自信がないか
あるシステムがほぼ確実なら:
- エントロピーは低い
毎回とても予想しにくいなら:
- エントロピーは高い
エントロピーの一番素朴な意味は、結局これです。
平均的にどれだけ不確実か。
flowchart LR A["確実性が高い<br/>エントロピーが低い"] --> E["例:99% 晴れ<br/>ほとんど迷わない"] B["不確実性が高い<br/>エントロピーが高い"] --> F["例:50% 晴れ 50% 雨<br/>まったく読めない"]
style A fill:#e8f5e9,stroke:#2e7d32,color:#333 style B fill:#ffebee,stroke:#c62828,color:#333H(X) = -Σ p(x) × log2(p(x))
def entropy(probs): """エントロピーを計算する(単位は bit)""" probs = np.array(probs) # log(0) を避ける probs = probs[probs > 0] return -np.sum(probs * np.log2(probs))
# 例1:公平なコイン(最大の不確実性)h1 = entropy([0.5, 0.5])print(f"公平なコインのエントロピー: {h1:.3f} bit") # 1.0
# 例2:偏ったコインh2 = entropy([0.9, 0.1])print(f"偏ったコイン(0.9, 0.1)のエントロピー: {h2:.3f} bit") # 0.469
# 例3:必然的な事象(不確実性なし)h3 = entropy([1.0, 0.0])print(f"必然的な事象のエントロピー: {h3:.3f} bit") # 0.0
# 例4:公平なサイコロh4 = entropy([1/6]*6)print(f"公平なサイコロのエントロピー: {h4:.3f} bit") # 2.585期待される出力:
公平なコインのエントロピー: 1.000 bit偏ったコイン(0.9, 0.1)のエントロピー: 0.469 bit必然的な事象のエントロピー: -0.000 bit公平なサイコロのエントロピー: 2.585 bit-0.000 は浮動小数点の丸めによる表示です。概念としては、エントロピーは正確に 0 です。
可視化:コインのエントロピーが p によってどう変わるか
Section titled “可視化:コインのエントロピーが p によってどう変わるか”p_values = np.linspace(0.001, 0.999, 1000)entropies = [-p * np.log2(p) - (1-p) * np.log2(1-p) for p in p_values]
plt.figure(figsize=(8, 5))plt.plot(p_values, entropies, color='steelblue', linewidth=2)plt.xlabel('表が出る確率 p')plt.ylabel('エントロピー H (bit)')plt.title('二値分布のエントロピー:p=0.5 で最大(最も不確実)')plt.axvline(x=0.5, color='red', linestyle='--', alpha=0.5, label='p=0.5(最大エントロピー)')plt.legend()plt.grid(True, alpha=0.3)plt.show()重要なポイント:p = 0.5 のときエントロピーは最大(最も不確実)になり、p = 0 または 1 のときエントロピーは 0(完全に確実)になります。
AI におけるエントロピーの応用
Section titled “AI におけるエントロピーの応用”| 応用 | 説明 |
|---|---|
| 決定木 | 情報利得(エントロピーの減少量)を使って最適な分割特徴を選ぶ |
| モデル出力 | 分類モデルの出力確率分布のエントロピーが低いほど、モデルはより「自信がある」 |
| データ圧縮 | エントロピーはデータ圧縮の理論的な下限 |
| 言語モデル | 困惑度(Perplexity) = 2^(交差エントロピー)、モデルの良し悪しを測る |
三、交差エントロピー —— 「予測がどれくらい正確か」を測る
Section titled “三、交差エントロピー —— 「予測がどれくらい正確か」を測る”交差エントロピー = 分布 Q を使って分布 P のデータを符号化すると、平均して1サンプルあたり何ビット必要か。
初心者向けの言い方
Section titled “初心者向けの言い方”交差エントロピーは、まず次のように理解しても大丈夫です。
- 予測分布と真の分布がどれくらいずれているか
初心者にとっては、これで十分役に立ちます。 というのも、その後の分類モデルで本当に気にするのも、
- モデルが正しいクラスにより高い確率を与えているか
だからです。
Q と P が完全に同じなら → 交差エントロピー = P のエントロピー(最小値) Q と P の差が大きいなら → 交差エントロピーは P のエントロピーよりかなり大きくなる
H(P, Q) = -Σ p(x) × log2(q(x))
def cross_entropy(p, q): """交差エントロピーを計算する""" p, q = np.array(p), np.array(q) # log(0) を避ける q = np.clip(q, 1e-10, 1) return -np.sum(p * np.log2(q))
# 真の分布 PP = [0.7, 0.2, 0.1] # 3クラス問題
# 予測分布 Q(予測の質が異なる)Q_good = [0.65, 0.25, 0.10] # 良い予測Q_bad = [0.33, 0.33, 0.34] # 悪い予測(ほぼ一様に予測)Q_wrong = [0.1, 0.1, 0.8] # 間違った予測
print(f"P のエントロピー: {entropy(P):.4f}")print(f"良い予測の交差エントロピー: {cross_entropy(P, Q_good):.4f}")print(f"悪い予測の交差エントロピー: {cross_entropy(P, Q_bad):.4f}")print(f"間違った予測の交差エントロピー: {cross_entropy(P, Q_wrong):.4f}")期待される出力:
P のエントロピー: 1.1568良い予測の交差エントロピー: 1.1672悪い予測の交差エントロピー: 1.5952間違った予測の交差エントロピー: 3.0219交差エントロピーを損失関数として使う
Section titled “交差エントロピーを損失関数として使う”分類タスクでは、交差エントロピーを最小化する = モデルの予測を真の分布にできるだけ近づける ことです。
# 二値分類の交差エントロピー損失def binary_cross_entropy(y_true, y_pred): """二値分類の交差エントロピー(PyTorch の BCELoss と等価)""" y_pred = np.clip(y_pred, 1e-10, 1 - 1e-10) return -np.mean( y_true * np.log(y_pred) + (1 - y_true) * np.log(1 - y_pred) )
# 真のラベルy_true = np.array([1, 0, 1, 1, 0])
# 予測の質が異なる出力predictions = { "完璧な予測": np.array([1.0, 0.0, 1.0, 1.0, 0.0]), "良い予測": np.array([0.9, 0.1, 0.8, 0.9, 0.2]), "悪い予測": np.array([0.6, 0.4, 0.6, 0.6, 0.4]), "完全に間違い": np.array([0.1, 0.9, 0.1, 0.1, 0.9]),}
for name, y_pred in predictions.items(): loss = binary_cross_entropy(y_true, y_pred) print(f"{name:10s} → 交差エントロピー損失 = {loss:.4f}")出力:
完璧な予測 → 交差エントロピー損失 ≈ 0.0000良い予測 → 交差エントロピー損失 ≈ 0.1525悪い予測 → 交差エントロピー損失 ≈ 0.5108完全に間違い → 交差エントロピー損失 ≈ 2.3026このコードは np.log、つまり自然対数を使っているため、単位は nat です。これは多くの深層学習フレームワークの交差エントロピー損失と一致します。
可視化:予測の正確さ vs 損失
Section titled “可視化:予測の正確さ vs 損失”# 真のラベルが y=1 のとき、予測値 p と損失の関係p_pred = np.linspace(0.01, 0.99, 100)
# y=1 のとき、loss = -log(p)loss_y1 = -np.log(p_pred)
# y=0 のとき、loss = -log(1-p)loss_y0 = -np.log(1 - p_pred)
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
axes[0].plot(p_pred, loss_y1, color='steelblue', linewidth=2)axes[0].set_xlabel('モデルの予測 P(y=1)')axes[0].set_ylabel('損失')axes[0].set_title('真のラベル y=1 のときの損失\n予測が 1 に近いほど損失は小さい')axes[0].grid(True, alpha=0.3)
axes[1].plot(p_pred, loss_y0, color='coral', linewidth=2)axes[1].set_xlabel('モデルの予測 P(y=1)')axes[1].set_ylabel('損失')axes[1].set_title('真のラベル y=0 のときの損失\n予測が 0 に近いほど損失は小さい')axes[1].grid(True, alpha=0.3)
plt.tight_layout()plt.show()解釈:交差エントロピー損失にはとても良い性質があります。予測が外れたとき、たとえば y=1 なのにモデルが 0.01 を出した場合、損失は急激に大きくなり、誤った予測を強く罰します。
初心者向けの分類の直感
Section titled “初心者向けの分類の直感”交差エントロピーは、まず次のように考えるとよいです。
- 正解にどれだけ信頼を置いたか
たとえば正しいクラスが 猫 なのに、大部分の確率を 犬 に割り当てていたら、
交差エントロピーは大きくなります。
逆に、正しいクラスに確率をしっかり割り当てていれば、
交差エントロピーは小さくなります。
つまり、交差エントロピーでまず覚えるべきなのは数式ではなく、次の一文です。
モデルが正解により多くの確率を割り当てるほど、損失は通常小さくなる。
単一サンプルの交差エントロピーの最小例をもう一度見る
Section titled “単一サンプルの交差エントロピーの最小例をもう一度見る”labels = ["猫", "犬", "鳥"]true_label = "犬"pred_probs = [0.1, 0.7, 0.2]
true_index = labels.index(true_label)loss = -np.log(pred_probs[true_index])
print("正しいクラス:", true_label)print("モデルの予測:", dict(zip(labels, pred_probs)))print("交差エントロピー損失:", round(loss, 4))期待される出力:
正しいクラス: 犬モデルの予測: {'猫': 0.1, '犬': 0.7, '鳥': 0.2}交差エントロピー損失: 0.3567この例は初心者にとても向いています。抽象的な分布の話を、いつもの分類問題に戻して考えられるからです。
- 正解はどれか
- そのクラスにどれだけ確率を与えたか
- それがそのままどれくらいの損失になるか
四、KLダイバージェンス —— 2つの分布の「距離」
Section titled “四、KLダイバージェンス —— 2つの分布の「距離」”KLダイバージェンス(KL Divergence)= ある分布 Q を使って真の分布 P の代わりにすると、どれだけ「余計に」ビットが必要になるか。
なぜ KLダイバージェンス は少し分かりにくいのか?
Section titled “なぜ KLダイバージェンス は少し分かりにくいのか?”見た目は「分布間の距離」に見えるのに、 実は対称ではありません。
初心者には、まず次の理解が安定です。
- KL は普通の幾何学的な距離ではない
- これは「真の分布を近似するとき、間違った分布を使ったらどれくらい余計にコストがかかるか」に近い
この直感があれば、次のような場面での役割も理解しやすくなります。
- VAE
- 蒸留
- RLHF
KL(P || Q) = 交差エントロピー(P, Q) - エントロピー(P)
def kl_divergence(p, q): """KLダイバージェンスを計算する""" p, q = np.array(p), np.array(q) q = np.clip(q, 1e-10, 1) p = np.clip(p, 1e-10, 1) return np.sum(p * np.log2(p / q))
P = [0.7, 0.2, 0.1]Q1 = [0.65, 0.25, 0.10] # P に近いQ2 = [0.33, 0.33, 0.34] # P から遠い
print(f"KL(P || Q1): {kl_divergence(P, Q1):.4f} (Q1 は P に近い)")print(f"KL(P || Q2): {kl_divergence(P, Q2):.4f} (Q2 は P から遠い)")print(f"KL(P || P): {kl_divergence(P, P):.4f} (P 自身)")期待される出力:
KL(P || Q1): 0.0105 (Q1 は P に近い)KL(P || Q2): 0.4384 (Q2 は P から遠い)KL(P || P): 0.0000 (P 自身)KLダイバージェンスの性質
Section titled “KLダイバージェンスの性質”| 性質 | 説明 |
|---|---|
| 非負性 | KL(P || Q) ≥ 0。等号が成り立つのは P = Q のときだけ |
| 非対称 | KL(P || Q) ≠ KL(Q || P)。本当の「距離」ではない |
| P=Q のとき 0 | 2つの分布が完全に同じなら、KLダイバージェンスは 0 |
# 非対称性を確認するP = [0.7, 0.2, 0.1]Q = [0.33, 0.33, 0.34]
print(f"KL(P || Q) = {kl_divergence(P, Q):.4f}")print(f"KL(Q || P) = {kl_divergence(Q, P):.4f}")print("両者は等しくありません!")期待される出力:
KL(P || Q) = 0.4384KL(Q || P) = 0.4807両者は等しくありません!可視化:分布の差が大きくなると KLダイバージェンス はどう変わるか
Section titled “可視化:分布の差が大きくなると KLダイバージェンス はどう変わるか”# 二値分布:P = [0.8, 0.2]、Q を [0.01, 0.99] から [0.99, 0.01] まで変化させるp = 0.8q_values = np.linspace(0.01, 0.99, 200)
kl_values = [kl_divergence([p, 1-p], [q, 1-q]) for q in q_values]
plt.figure(figsize=(8, 5))plt.plot(q_values, kl_values, color='steelblue', linewidth=2)plt.axvline(x=p, color='red', linestyle='--', label=f'q = p = {p}(KL=0)')plt.xlabel('q の値')plt.ylabel('KL(P || Q)')plt.title(f'KLダイバージェンス:P=[{p}, {1-p}]、Q=[q, 1-q]')plt.legend()plt.grid(True, alpha=0.3)plt.show()AI における KLダイバージェンス の応用
Section titled “AI における KLダイバージェンス の応用”| 応用 | 説明 |
|---|---|
| VAE | 潜在変数の分布を標準正規分布に近づける:KL(q(z|x) || N(0,1)) |
| 知識蒸留 | 小さなモデルの出力分布を大きなモデルに近づける:KLダイバージェンスを最小化する |
| RLHF | 微調整後のモデルが元のモデルから離れすぎないようにする |
| 方策最適化 | PPO で方策更新の大きさを制限する |
五、3つの関係
Section titled “五、3つの関係”flowchart TD H["エントロピー H(P)<br/>P 自身の不確実性<br/>情報の下限"] CE["交差エントロピー H(P,Q)<br/>Q で P のデータを符号化する<br/>= エントロピー + KLダイバージェンス"] KL["KLダイバージェンス KL(P||Q)<br/>Q が P より余計に必要とするビット<br/>= 交差エントロピー - エントロピー"]
CE --> H CE --> KL H -.->|"H(P,Q) = H(P) + KL(P||Q)"| CE
style H fill:#e3f2fd,stroke:#1565c0,color:#333 style CE fill:#fff3e0,stroke:#e65100,color:#333 style KL fill:#e8f5e9,stroke:#2e7d32,color:#333核心的な関係:交差エントロピー = エントロピー + KLダイバージェンス
P = [0.7, 0.2, 0.1]Q = [0.5, 0.3, 0.2]
h = entropy(P)ce = cross_entropy(P, Q)kl = kl_divergence(P, Q)
print(f"エントロピー H(P): {h:.4f}")print(f"交差エントロピー H(P,Q): {ce:.4f}")print(f"KLダイバージェンス: {kl:.4f}")print(f"H(P) + KL = {h + kl:.4f}") # = 交差エントロピー ✓期待される出力:
エントロピー H(P): 1.1568交差エントロピー H(P,Q): 1.2796KLダイバージェンス: 0.1228H(P) + KL = 1.2796初心者がまず覚えるとよい比較表
Section titled “初心者がまず覚えるとよい比較表”| 概念 | まず覚えるべき問い |
|---|---|
| 情報量 | この出来事はどれくらい意外? |
| エントロピー | 全体として平均どれくらい不確実? |
| 交差エントロピー | 予測と真実はどれくらい違う? |
| KLダイバージェンス | 間違った分布を使うと、どれくらい余計にコストがかかる? |
この表は初心者に特に役立ちます。第4章を「公式のかたまり」ではなく、直感の地図として見直せるからです。
ここまで学んだら、次はどこへ進むべき?
Section titled “ここまで学んだら、次はどこへ進むべき?”確率と統計の章をここまで読んだら、次に持っていくべきなのは、さらに多くの公式ではなく、次のような問いです。
- 確率、交差エントロピー、KLダイバージェンスは、実際にどうやって loss になるのか?
- モデルはなぜ絶対的な結論ではなく、いつも確率を出力するのか?
- こうした「不確実性を表す言葉」は、機械学習の中でどのように学習や評価の道具になるのか?
次に読むのにおすすめなのは、たとえば次のページです。
このページを終えたら、この evidence card を残します。
- 確率過程
- 事象、分布、サンプル、尤度、エントロピー、またはベイズ更新
- シミュレーションまたは式
- 不確実性を可視化するために使ったコードまたは式
- 出力
- probability、sample statistic、interval、entropy、または更新された信念
- 失敗確認
- ベースレートの混同、p値の誤用、サンプルバイアス、または確率と確実性の混同
- 期待される成果
- 数値結果と平易な言葉での解釈
| 概念 | 直感 | 値域 |
|---|---|---|
| 情報量 | ある出来事がどれだけ「意外」か | ≥ 0 |
| エントロピー | ある分布がどれだけ「不確実」か | ≥ 0 |
| 交差エントロピー | 予測分布と真の分布の差 | ≥ H(P) |
| KLダイバージェンス | 2つの分布の「距離」 | ≥ 0 |
この節で一番持ち帰るべきこと
Section titled “この節で一番持ち帰るべきこと”- 情報量の最も大事な直感は「意外なほど情報が大きい」
- エントロピーの最も大事な直感は「平均してどれくらい不確実か」
- 交差エントロピーの最も大事な直感は「予測と真実がどれくらい違うか」
- KLダイバージェンスの最も大事な直感は「間違った分布を使うとどれくらい余計にコストがかかるか」
手を動かして練習しよう
Section titled “手を動かして練習しよう”練習 1:エントロピーを計算する
Section titled “練習 1:エントロピーを計算する”次の分布のエントロピーを計算し、どれが最も「不確実」か説明してください。
- [0.25, 0.25, 0.25, 0.25](4面サイコロ)
- [0.97, 0.01, 0.01, 0.01](ほぼ確実)
- [0.4, 0.3, 0.2, 0.1](不均一)
参考実装:
distributions = [ [0.25, 0.25, 0.25, 0.25], [0.97, 0.01, 0.01, 0.01], [0.4, 0.3, 0.2, 0.1],]
for probs in distributions: print(f"{probs} -> entropy={entropy(probs):.4f} bits")期待される出力:
[0.25, 0.25, 0.25, 0.25] -> entropy=2.0000 bits[0.97, 0.01, 0.01, 0.01] -> entropy=0.2419 bits[0.4, 0.3, 0.2, 0.1] -> entropy=1.8464 bits最初の分布が最も不確実です。4つの結果がすべて同じ確率で起こるからです。
練習 2:交差エントロピー損失
Section titled “練習 2:交差エントロピー損失”3クラス分類問題です。真のラベルは第2クラス(one-hot: [0, 1, 0])、モデルの softmax 出力は [0.1, 0.7, 0.2] です。交差エントロピー損失を計算してください。もしモデルの出力が [0.05, 0.9, 0.05] に変わったら、損失はどう変わるでしょうか?
参考実装:
P = np.array([0, 1, 0])Q1 = np.array([0.1, 0.7, 0.2])Q2 = np.array([0.05, 0.9, 0.05])
loss1 = -np.sum(P * np.log(Q1))loss2 = -np.sum(P * np.log(Q2))
print(f"Loss with [0.1, 0.7, 0.2]: {loss1:.4f} nats")print(f"Loss with [0.05, 0.9, 0.05]: {loss2:.4f} nats")期待される出力:
Loss with [0.1, 0.7, 0.2]: 0.3567 natsLoss with [0.05, 0.9, 0.05]: 0.1054 nats2つ目の予測は正しいクラスにより高い確率を割り当てているため、損失が小さくなります。
練習 3:KLダイバージェンスを可視化する
Section titled “練習 3:KLダイバージェンスを可視化する”真の分布 P = [0.6, 0.3, 0.1] を固定し、Q をあるパラメータに沿って変化させたとき(たとえば q1 を 0.1 から 0.9 まで変える)、KL(P||Q) の変化曲線を描いてみましょう。
参考実装:
P = np.array([0.6, 0.3, 0.1])q1_values = np.linspace(0.1, 0.9, 200)kl_values = []
for q1 in q1_values: # 残りの確率を 3:1 の比率で後ろ2つのクラスに分ける。 Q = np.array([q1, (1 - q1) * 0.75, (1 - q1) * 0.25]) kl_values.append(kl_divergence(P, Q))
plt.figure(figsize=(8, 5))plt.plot(q1_values, kl_values, color="steelblue", linewidth=2)plt.axvline(x=0.6, color="red", linestyle="--", label="Q = P")plt.xlabel("q1")plt.ylabel("KL(P || Q)")plt.title("KLダイバージェンスは Q が P と一致すると最小になる")plt.legend()plt.grid(alpha=0.3)plt.show()
for q1 in [0.1, 0.6, 0.9]: Q = np.array([q1, (1 - q1) * 0.75, (1 - q1) * 0.25]) print(f"q1={q1:.1f}, Q={Q.round(3)}, KL={kl_divergence(P, Q):.4f}")期待される出力:
q1=0.1, Q=[0.1 0.675 0.225], KL=1.0830q1=0.6, Q=[0.6 0.3 0.1], KL=-0.0000q1=0.9, Q=[0.9 0.075 0.025], KL=0.4490操作例と確認ポイント
- 3 つのエントロピーは
2.0000、約0.2419、約1.8464bits です。4 つの結果が一様な分布が最も不確実です。どの結果も優先されないからです。 - 3 クラスのクロスエントロピー例では、loss は約
0.3567と0.1054nats です。正解クラスにより高い確率を与えると loss は下がります。 - よい説明は訓練につなげます。クロスエントロピーは、正解クラスへの適切な自信を評価し、誤ったクラスへ高い確率を置くことを罰します。