カルバックライブラー情報量
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}\]pythonでサイコロの標本確率と母確率のカルバックライブラー情報量を計算する
import pandas as pd
import numpy as np
import random
def calc(K):
samples = np.array(list(range(6)))
for k in range(K):
i = random.choice([0, 1, 2, 3, 4, 5])
samples[i] += 1
sample = samples / K
base = np.zeros(6)
base += 1/6
# KL距離を計算
D = 0
for i in range(6):
D += sample[i] * np.log(sample[i]/base[i])
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))
"""
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))
"""