• home
  • about
  • 全ての投稿
  • ソフトウェア・ハードウェアの設定のまとめ
  • 分析関連のまとめ
  • ヘルスケア関連のまとめ
  • 生涯学習関連のまとめ

カルバックライブラー情報量

date: 2021-12-21 excerpt: カルバックライブラー情報量について

tag: statisticsカルバックライブラー情報量KL情報量KLダイバージェンス


カルバックライブラー情報量について

概要

  • エントロピーを変形して得られる情報量
  • 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ダイバージェンスが小さくなるので期待した結果が得られた

  • colab

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))
  • colab


statisticsカルバックライブラー情報量KL情報量KLダイバージェンス Share Tweet