2つ以上の確率変数を同時に扱う場合、それらの不確実性をどう測るかが重要になります。結合エントロピーは2つの変数の「全体の不確実性」を、条件付きエントロピーは「一方を知った後の残りの不確実性」を表します。これらは情報理論における基本的な量であり、相互情報量やデータ圧縮の理解に不可欠です。
本記事の内容
- 結合エントロピーの定義と性質
- 条件付きエントロピーの定義と直感
- エントロピーの連鎖律
- 独立な確率変数の場合
- Pythonでの計算と可視化
前提知識
この記事を読む前に、以下の記事を読んでおくと理解が深まります。
結合エントロピーの定義
2つの離散確率変数 $X$, $Y$ の結合エントロピー(joint entropy)は次のように定義されます。
$$ \boxed{H(X, Y) = -\sum_{x}\sum_{y} P(x, y) \log P(x, y)} $$
ここで $P(x, y)$ は $X = x$ かつ $Y = y$ となる結合確率です。
結合エントロピーは「$X$ と $Y$ の組を観測したときの平均的な驚き(不確実性)」を表します。
性質
- 非負性: $H(X, Y) \geq 0$
- 上界: $H(X, Y) \leq H(X) + H(Y)$(等号は $X, Y$ が独立のとき)
- 下界: $H(X, Y) \geq \max(H(X), H(Y))$
性質2は直感的に理解できます。2つの変数の全体の不確実性は、それぞれの不確実性の和以下です。なぜなら、$X$ と $Y$ の間に関係(相関)があれば、片方を知ることでもう片方の不確実性が減るからです。
条件付きエントロピーの定義
$X$ を知った後の $Y$ の残りの不確実性を表す条件付きエントロピー(conditional entropy)は:
$$ \boxed{H(Y|X) = -\sum_{x}\sum_{y} P(x, y) \log P(y|x)} $$
これは条件付き自己情報量 $-\log P(y|x)$ の結合分布に関する期待値です。
別の表現
条件付きエントロピーを $X$ の各値で平均したものとしても書けます。
$$ H(Y|X) = \sum_{x} P(x) H(Y|X=x) $$
ここで:
$$ H(Y|X=x) = -\sum_{y} P(y|x) \log P(y|x) $$
は $X = x$ が与えられたときの $Y$ のエントロピーです。
導出
$H(Y|X)$ の定義式を変形します。
$$ \begin{align} H(Y|X) &= -\sum_{x}\sum_{y} P(x, y) \log P(y|x) \\ &= -\sum_{x}\sum_{y} P(x) P(y|x) \log P(y|x) \\ &= -\sum_{x} P(x) \sum_{y} P(y|x) \log P(y|x) \\ &= \sum_{x} P(x) H(Y|X=x) \end{align} $$
直感
条件付きエントロピー $H(Y|X)$ は:
- $X$ と $Y$ が独立なら $H(Y|X) = H(Y)$($X$ を知っても $Y$ の不確実性は変わらない)
- $Y$ が $X$ で完全に決まるなら $H(Y|X) = 0$($X$ を知れば $Y$ の不確実性はゼロ)
- 一般に $0 \leq H(Y|X) \leq H(Y)$(条件付けは平均的にエントロピーを減らす)
エントロピーの連鎖律
結合エントロピーは次のように分解できます。
$$ \boxed{H(X, Y) = H(X) + H(Y|X)} $$
これが連鎖律(chain rule)です。
導出
$$ \begin{align} H(X, Y) &= -\sum_{x}\sum_{y} P(x, y) \log P(x, y) \\ &= -\sum_{x}\sum_{y} P(x, y) \log \left[P(x) P(y|x)\right] \\ &= -\sum_{x}\sum_{y} P(x, y) \log P(x) – \sum_{x}\sum_{y} P(x, y) \log P(y|x) \\ &= -\sum_{x} \log P(x) \underbrace{\sum_{y} P(x, y)}_{= P(x)} + H(Y|X) \\ &= -\sum_{x} P(x) \log P(x) + H(Y|X) \\ &= H(X) + H(Y|X) \end{align} $$
対称性より:
$$ H(X, Y) = H(Y) + H(X|Y) $$
も成り立ちます。
$n$ 変数への一般化
$$ H(X_1, X_2, \dots, X_n) = \sum_{i=1}^{n} H(X_i | X_1, \dots, X_{i-1}) $$
独立な確率変数の場合
$X$ と $Y$ が独立のとき $P(y|x) = P(y)$ なので:
$$ H(Y|X) = H(Y) $$
したがって連鎖律より:
$$ \boxed{H(X, Y) = H(X) + H(Y) \quad \text{($X, Y$ が独立のとき)}} $$
独立な場合、結合エントロピーは単にそれぞれのエントロピーの和になります。
具体例
天気 $X \in \{\text{晴れ}, \text{雨}\}$ と傘 $Y \in \{\text{持つ}, \text{持たない}\}$ の同時分布を考えます。
| 持つ | 持たない | $P(X)$ | |
|---|---|---|---|
| 晴れ | 0.10 | 0.50 | 0.60 |
| 雨 | 0.25 | 0.15 | 0.40 |
| $P(Y)$ | 0.35 | 0.65 | 1.00 |
$$ \begin{align} H(X) &= -(0.6\log_2 0.6 + 0.4\log_2 0.4) \approx 0.971 \text{ bit} \\ H(Y) &= -(0.35\log_2 0.35 + 0.65\log_2 0.65) \approx 0.934 \text{ bit} \end{align} $$
$$ \begin{align} H(X, Y) &= -(0.10\log_2 0.10 + 0.50\log_2 0.50 + 0.25\log_2 0.25 + 0.15\log_2 0.15) \\ &\approx 1.755 \text{ bit} \end{align} $$
連鎖律から:
$$ H(Y|X) = H(X, Y) – H(X) \approx 1.755 – 0.971 = 0.784 \text{ bit} $$
$H(Y|X) = 0.784 < H(Y) = 0.934$ なので、天気を知ることで傘の不確実性が減ることが確認できます。
Pythonでの実装
エントロピーの計算
import numpy as np
import matplotlib.pyplot as plt
def entropy(probs):
"""エントロピーを計算(底2)"""
probs = np.array(probs).flatten()
probs = probs[probs > 0]
return -np.sum(probs * np.log2(probs))
def joint_entropy(joint_probs):
"""結合エントロピーを計算"""
return entropy(joint_probs)
def conditional_entropy(joint_probs):
"""H(Y|X) を計算(joint_probs は行が X, 列が Y)"""
joint = np.array(joint_probs)
px = joint.sum(axis=1) # X の周辺分布
H_Y_given_X = 0.0
for i in range(joint.shape[0]):
if px[i] > 0:
p_y_given_x = joint[i, :] / px[i]
H_Y_given_X += px[i] * entropy(p_y_given_x)
return H_Y_given_X
# --- 天気と傘の例 ---
joint = np.array([
[0.10, 0.50], # 晴れ: (持つ, 持たない)
[0.25, 0.15], # 雨: (持つ, 持たない)
])
px = joint.sum(axis=1) # P(X)
py = joint.sum(axis=0) # P(Y)
H_X = entropy(px)
H_Y = entropy(py)
H_XY = joint_entropy(joint)
H_Y_given_X = conditional_entropy(joint)
H_X_given_Y = H_XY - H_Y
print("=== 天気(X)と傘(Y)の例 ===")
print(f"H(X) = {H_X:.4f} bit")
print(f"H(Y) = {H_Y:.4f} bit")
print(f"H(X,Y) = {H_XY:.4f} bit")
print(f"H(Y|X) = {H_Y_given_X:.4f} bit")
print(f"H(X|Y) = {H_X_given_Y:.4f} bit")
print(f"H(X)+H(Y|X) = {H_X + H_Y_given_X:.4f} bit (= H(X,Y))")
print(f"H(X)+H(Y) = {H_X + H_Y:.4f} bit (>= H(X,Y))")
連鎖律とベン図の可視化
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Circle
# --- エントロピーのベン図 ---
fig, ax = plt.subplots(figsize=(8, 6))
# 2つの円
c1 = Circle((0.35, 0.5), 0.3, fill=False, edgecolor='blue', linewidth=2, label='H(X)')
c2 = Circle((0.65, 0.5), 0.3, fill=False, edgecolor='red', linewidth=2, label='H(Y)')
ax.add_patch(c1)
ax.add_patch(c2)
# ラベル
ax.text(0.20, 0.5, 'H(X|Y)', fontsize=13, ha='center', va='center', color='blue')
ax.text(0.80, 0.5, 'H(Y|X)', fontsize=13, ha='center', va='center', color='red')
ax.text(0.50, 0.5, 'I(X;Y)', fontsize=13, ha='center', va='center', color='purple')
ax.text(0.50, 0.05, 'H(X,Y)', fontsize=14, ha='center', va='center',
bbox=dict(boxstyle='round', facecolor='lightyellow'))
# 数値(天気と傘の例)
joint = np.array([[0.10, 0.50], [0.25, 0.15]])
px = joint.sum(axis=1)
py = joint.sum(axis=0)
H_X = entropy(px)
H_Y = entropy(py)
H_XY = joint_entropy(joint)
I_XY = H_X + H_Y - H_XY
ax.text(0.20, 0.35, f'{H_X - I_XY:.3f}', fontsize=11, ha='center', va='center', color='blue')
ax.text(0.80, 0.35, f'{H_Y - I_XY:.3f}', fontsize=11, ha='center', va='center', color='red')
ax.text(0.50, 0.35, f'{I_XY:.3f}', fontsize=11, ha='center', va='center', color='purple')
ax.set_xlim(0, 1)
ax.set_ylim(0, 1)
ax.set_aspect('equal')
ax.set_title('Entropy Venn Diagram (Weather & Umbrella)', fontsize=14)
ax.legend(loc='upper right', fontsize=11)
ax.axis('off')
plt.tight_layout()
plt.show()
独立性とエントロピーの関係
import numpy as np
import matplotlib.pyplot as plt
# --- 独立度合いとエントロピーの変化 ---
# パラメータ alpha で独立性を制御
# alpha=0: 完全に独立, alpha=1: 強い依存
alphas = np.linspace(0, 0.9, 50)
H_XY_list = []
H_X_list = []
H_Y_list = []
H_Y_given_X_list = []
for alpha in alphas:
# 2x2 の結合分布を作成
# 独立分布: px=[0.5,0.5], py=[0.5,0.5] → joint = [[0.25,0.25],[0.25,0.25]]
# 依存を加える
joint = np.array([
[0.25 + alpha * 0.25, 0.25 - alpha * 0.25],
[0.25 - alpha * 0.25, 0.25 + alpha * 0.25],
])
joint = np.clip(joint, 1e-10, None)
joint /= joint.sum()
px = joint.sum(axis=1)
py = joint.sum(axis=0)
H_XY_list.append(joint_entropy(joint))
H_X_list.append(entropy(px))
H_Y_list.append(entropy(py))
H_Y_given_X_list.append(conditional_entropy(joint))
fig, ax = plt.subplots(figsize=(10, 6))
ax.plot(alphas, H_XY_list, 'b-', linewidth=2, label='H(X,Y)')
ax.plot(alphas, H_X_list, 'g--', linewidth=2, label='H(X)')
ax.plot(alphas, H_Y_list, 'r--', linewidth=2, label='H(Y)')
ax.plot(alphas, H_Y_given_X_list, 'm-', linewidth=2, label='H(Y|X)')
ax.plot(alphas, np.array(H_X_list) + np.array(H_Y_list), 'k:', linewidth=2, label='H(X)+H(Y)')
ax.set_xlabel('Dependence parameter α', fontsize=12)
ax.set_ylabel('Entropy [bit]', fontsize=12)
ax.set_title('Entropy quantities vs dependence', fontsize=13)
ax.legend(fontsize=11)
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
まとめ
本記事では、結合エントロピーと条件付きエントロピーについて解説しました。
- 結合エントロピー: $H(X, Y) = -\sum_{x,y} P(x,y) \log P(x,y)$
- 条件付きエントロピー: $H(Y|X) = -\sum_{x,y} P(x,y) \log P(y|x)$
- 連鎖律: $H(X, Y) = H(X) + H(Y|X)$
- 独立のとき: $H(X, Y) = H(X) + H(Y)$
- 条件付けは平均的にエントロピーを減少させる: $H(Y|X) \leq H(Y)$
次のステップとして、以下の記事も参考にしてください。