カルバックライブラー情報量
date: 2021-12-21 excerpt: カルバックライブラー情報量について
カルバックライブラー情報量について
概要
- エントロピーを変形して得られる情報量
- 2つの確率分布の違いを測る指標
- KL情報量やKLダイバージェンスとも呼ばれる
定義
情報量の定義
\[- \log p\]エントロピーの定義
\[- \sum_{k=1}^{n} p_k \log p_k\]カルバックライブラー情報量の定義(PからQへのダイバージェンス)
\[D_{KL}(P\|Q) = \sum_{k=1}^{n} p_k \log \frac{p_k}{q_k}\]最小の例
from scipy.stats import entropy
# リスト形式の分布 (P: 真の分布, Q: 近似分布 と仮定)
P = [0.1, 0.5, 0.2, 0.2]
Q = [0.2, 0.4, 0.2, 0.2]
# KL情報量の計算: D_KL(P || Q)
kl_divergence = entropy(pk=P, qk=Q)
print(f"KL Divergence: {kl_divergence:.6f}")
# 出力例: KL Divergence: 0.042257
Pythonでサイコロの標本確率と母確率のカルバックライブラー情報量を計算する
import numpy as np
import random
def calc(K):
# 標本の度数を初期化
counts = np.zeros(6, dtype=float)
for _ in range(K):
i = random.choice([0, 1, 2, 3, 4, 5])
counts[i] += 1
sample = counts / counts.sum()
# 一様な母分布
base = np.full(6, 1/6, dtype=float)
# KLダイバージェンスを計算
# ゼロ確率は項が0になるので除外
mask = sample > 0
D = float(np.sum(sample[mask] * np.log(sample[mask] / base[mask])))
print(f"サンプルサイズ={K}, KLダイバージェンス={D}")
calc(K=50)
for k in [50, 100, 200, 400, 800, 1600]:
calc(K=k)
出力
サンプルサイズ=50, KLダイバージェンス=0.355223417
サンプルサイズ=100, KLダイバージェンス=0.197589872
サンプルサイズ=200, KLダイバージェンス=0.089810843
サンプルサイズ=400, KLダイバージェンス=0.042661367
サンプルサイズ=800, KLダイバージェンス=0.024547575
サンプルサイズ=1600, KLダイバージェンス=0.010081105
-
サンプルサイズが大きくなるほどKLダイバージェンスが小さくなるので期待した結果が得られた
2つのテキストのKLダイバージェンスを計算する
from sklearn.feature_extraction.text import CountVectorizer
import numpy as np
def calculate_kl_divergence(text1, text2):
# 文章を単語に分割し、それぞれの単語の頻度をカウント
vectorizer = CountVectorizer().fit([text1, text2])
vector1 = vectorizer.transform([text1]).toarray()[0] + 1 # smoothing
vector2 = vectorizer.transform([text2]).toarray()[0] + 1 # smoothing
print(vectorizer.get_feature_names_out())
print(vector1)
print(vector2)
# 各単語の頻度を確率分布に変換
prob_dist1 = vector1 / vector1.sum()
prob_dist2 = vector2 / vector2.sum()
# KLダイバージェンスを計算
kl_divergence = np.sum(prob_dist1 * np.log(prob_dist1 / prob_dist2))
return kl_divergence
text1 = "I like apples. Apples are very delicious. I eat apples every day."
text2 = "I like bananas. Bananas are very delicious. I eat bananas every day."
print(calculate_kl_divergence(text1, text2))