サケ時々ソフトコンピューティング

日本酒とソフトコンピューティングの備忘録

情報量まとめ

PRMLラボのアドベントカレンダーhttps://adventar.org/calendars/2186
5日目を担当します.M1のsumvoです.

研究のテーマがら情報量を扱うことがあり,何度も調べてはこれでいいのか?ってなっていたり忘れたりするので,備忘録的な意味も含め書いていきたいと思います.


基本的なことは↓でできるのですけども,ライブラリに無いものも多くスケール感を合わせたりするためにも全部自分でやっていこうみたいな感じです.

from scipy.stats import entropy# entropy, KLDの計算
from sklearn.metrics import mutual_info_score# MIの計算

まずは,シャノンエントロピーや平均情報量と一般的に言われている物です.エントロピーと言ったらこれみたいな感じです.


{ \displaystyle
H(X) = -\sum_{x}^{} P(x)log_{2}(P(x))
}


logの底が2の場合は単位がbitで在りJIS:ISO的にはこの単位がシャノンになる.eの時はnatで在り単位もnat.10の時はditであり,単位はハートレー

import numpy as np

print(np.histogram(data,bins=100)[0])
print(np.histogram(data,bins=100)[0]/data.shape[0])

pa = np.histogram(data,bins=100)[0]/data.shape[0]
print(-np.sum(pa*np.log2(pa)))
array([210,  81,  90,  64,  57, 115,  95,  78, 103,  82,  88,  95,  72,
        72, 169, 122, 129, 125,  90,  86,  58,  76,  85,  98,  98,  57,
        75, 112, 130, 226, 139, 160, 162, 140, 129, 133, 163, 146, 122,
        93,  88,  95, 133, 104, 101, 114,  96,  96, 107,  95, 100,  88,
        88,  92, 160, 168, 137, 111, 101, 120, 132, 155, 372, 276, 276,
       264, 220, 220, 239, 203, 193, 238, 261, 241, 307, 285, 357, 500,
       198, 194, 189, 211, 129, 138, 133, 200, 222, 219, 224, 213, 217,
       289, 351, 211, 229, 192, 194, 341, 346, 386], dtype=int64)

array([ 0.01281738,  0.00494385,  0.00549316,  0.00390625,  0.003479  ,
        0.00701904,  0.00579834,  0.00476074,  0.00628662,  0.00500488,
        0.00537109,  0.00579834,  0.00439453,  0.00439453,  0.01031494,
        0.00744629,  0.00787354,  0.00762939,  0.00549316,  0.00524902,
                                         .
                                         .
                                         .
6.4636211511753165


続いて結合エントロピー,joint entropyと呼ばれているものです.
{ \displaystyle
H(X, Y) = -\sum_{x,y}^{} P(x,y)log_{2}(P(x,y))
}
複数の場合
{ \displaystyle
H(X_{1},..., X_{n}) = -\sum_{1} ... \sum_{x_{n}}^{} P(x_{1}, ... ,x_{n}) log_{2}(P(x_{1},...,x_{n}))
}
結合エントロピーは常に元のエントロピーよりも上になります.また,2つのエントロピーの総和よりは下になります.

 H(X, Y) ≧ H(X)


 H(X, Y) ≦ H(X) + H(Y)


例 : 2つの結合エントロピー

import numpy as np

pab = np.histogram2d(data,data,bins=100)[0]/data.shape[0]
print(pab.shape)
print(-np.sum(pab*np.log2(pab+1e-15)))
(100, 100)
12.399404410313927

例 : 複数の結合エントロピー

import numpy as np

prnit(x.shape, y.shape, z.shape)
w = np.c_[x,y,z]
print(w.shape)
pabc = np.histogramdd(w, bins=100)[0] / w.shape[0]
print(pabc.shape)
print(-np.sum(pabc*np.log2(pabc+1e-15)))
((50, ), (50, ), (50, ))
(50, 3)
(100, 100, 100)
5.6438561897746533


そして相互情報量(Mutual Information : MI)
  \begin{eqnarray} 
 
I(X;Y) &=& H(X) - H(X|Y) \\\
         &=& H(Y) - H(Y|X) \\\
         &=& H(X) + H(Y) - H(X,Y) 
         &=& H(X,Y) - H(X|Y) - H(Y|X) 
\end{eqnarray}


import numpy as np

pa = np.histogram(data1,bins=100)[0]/data1.shape[0]
pb = np.histogram(data2,bins=100)[0]/data2.shape[0]
pab = np.histogram2d(data,data2,bins=100)[0]/data1.shape[0]
print((-np.sum(pa*np.log2(pa))) , (-np.sum(pb*np.log2(pb))) , (-np.sum(pab*np.log2(pab+1e-15))))

print(-np.sum(pab*np.log2(pab+1e-15)) + (-np.sum(pa*np.log2(pa))) + (-np.sum(pb*np.log2(pb))))
(6.4636211511753165, 6.3849326697480082, 12.399404410313927)
0.44914941060939739

実際sklearnとかにもある.CMIは計算できない.
作っている確率分布が違ってくるので出力も違う

from sklearn.metrics import mutual_info_score

mutual_info_score(data1, data2)
9.6793088338861271


そして条件付エントロピー(conditional entropy)
多分チェインルールにしたほうが楽


  
H(Y|X) = H(X,Y) - H(X)
  
H(X|Y) = H(X,Y) - H(Y)


そして条件付相互情報量(Conditional Mutual Information : CMI)
基本的には条件付エントロピーを式に入れているが,結合エントロピー重視で展開してくとこんな感じになる.結果結合エントロピーエントロピーだけの式になる.


  \begin{eqnarray} 
I(X;Y|Z) &=& \sum_{z∈Z} \sum_{y∈Y} \sum_{x∈X} p_{X,Y,Z}(x,y,z) log_{2} \frac{p_{X,Y,Z}(x,y,z)p_{z}(z)}{p_{X,Z}(x,z) p_{Y,Z}(y,z)}\\\
&=&  \sum_{z∈Z} \sum_{y∈Y} \sum_{x∈X} p_{Z}(z) p_{X,Y|Z}(x,y|z) log_{2} \frac{p_{X,Y|Z}(x,y|z)}{p_{X|Z}(x|z) p_{Y|Z}(y|z)}\\\
&=& H(X,Z) + H(Y,Z) - H(X,Y,Z) - H(Z)\\\
\end{eqnarray}


番外

交差エントロピー(クロスエントロピー)
  
H(p,q) = -\sum_{x}p(x) log(q(x))

import numpy as np

prob = np.array([
    [0.1,0.8,0.1],
    [0.3,0.4,0.3],
    [0.7,0.2,0.1],
    [0.3,0.3,0.4]])

label = np.array([
    [0,1,0],
    [1,0,0],
    [1,0,0],
    [0,0,1]])

print(-np.sum(label * np.log(prob)))
2.7000820314530332


カルバックライブラー情報量(カルバックライブラーダイバージェンス:KLD, 情報利得:Information gain)


    \begin{eqnarray} 
D_{KL}(P,Q) &=& -\sum_{i}P(x) log(\frac{Q(i)}{P(i)})\\\
&=& -\sum_{i}P(x) log(\frac{P(i)}{Q(i)})
\end{eqnarray}

import numpy as np
from scipy import stats

prob = np.array([
    [0.1,0.8,0.1],
    [0.3,0.4,0.3],
    [0.7,0.2,0.1],
    [0.3,0.3,0.4]])

label = np.array([
    [0,1,0],
    [1,0,0],
    [1,0,0],
    [0,0,1]])

print(stats.entropy(label,prob,2))#2つ入れるとKLD,1つだけだとエントロピー
array([ 0.61119621,  1.08746284,  1.169925  ])

とりあえず以上でまとめ終わりっ!!明日の人お願いします.