기본 콘텐츠로 건너뛰기

벡터와 행렬에 관련된 그림들

[ML]엔트로피와 정보획득(Entropy & Infomation Gain)

엔트로피와 정보획득(Entropy & Infomation Gain)

정보와 엔트로피(Infomation & Entropy)

정보의 기본개념은 이벤트, 확률변수, 분포와 같은 항목에서 정보의 양을 정량화하는 것으로 확률을 사용합니다. 직관적으로 정보를 정량화레 대한 기본 아이디어는 대상 이벤트에 대한 불확실성(uncertainty)을 측정한다는 것입니다.

드문 이벤트은 발생할 확률이 낮으므로 불확실성이 증가합니다. 불확실성을 감소시키기 위해 많은 정보가 필요합니다. 매우 다양한 정보량의 높은 정보를 가집니다. 예를 들어 여러 샘플이 포함된 박스에서 특정한 샘플을 선택하는 사건에서 낮은 확률은 샘플의 종류가 많은 경우일 것입니다. 이러한 상황은 데이터의 impurity가 높은 상황입니다. 이것을 엔트로피(entropy)로 나타냅니다. 반대의 상황, 높은 확률,은 낮은 엔트로피를 보입니다. 정리하면 다음과 같이 나타낼 수 있습니다.

  • 낮은 확률 이벤트 : 높은 정보(놀라움)
  • 높은 확률 이벤트 : 낮은 정보(놀랍지 않음)

사건(x)의 확률(p(x))로 부터 정보(info(x))를 정량화하기 위해 식 1과 같이 계산합니다.

$$\tag{식 1}\text{Info}(x)=h(x) = -\log(p(x))$$

결국 정보는 이벤트 설명에 필요한 메모리 수로 간주할 수 있습니다. 그러므로 식 1에서 2진법(bit 수)으로 나타내기 위해 log 2를 사용할 수 있지만 정보의 절대량보다는 그 변화가 더 중요하므로 일반적으로 자연로그를 사용합니다.

식 1에서 p(x)가 낮을수록 정보(h)는 증가함을 알 수 있습니다.

사건의 확률 1 → h=0

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_style("darkgrid")

다음 코드는 동전 던지기에서 앞면이 나올 확률 p=0.5인 경우 정보 h=1임을 계산한 것입니다.

p=0.5
h=-np.log(p); h
0.6931471805599453

주사위 던지기의 경우는 각 수의 확률은 1/6이며 이 확률은 동전던지기 보다 낮으므로 정보는 높습니다. 즉, 이 사건에 대해 나타내기 위해 더 많은 정보가 필요합니다.

p=1/6
h=-np.log(p); h
1.791759469228055

확률에 따른 정보의 변화를 시각적으로 나타내봅니다.

p=np.arange(0.01, 1, 0.1)
h=-np.log2(p)
plt.figure(figsize=(4,3))
plt.plot(p, h, 'o-')
plt.xlabel("Probability")
plt.ylabel("Information")
plt.show()

확률변수의 엔트로피 계산

확률변수들이 가진 정보를 정량화할 수 있습니다. 이 계산을 정보엔트로피, 간단하게 엔트로피라 합니다. 이 엔트로피는 해당분포에서 추출한 이벤트의 기대 정보량입니다. 그러므로 식 2와 같이 각 이벤트의 엔트로피들의 평균 즉, 기대값이 대상 분포의 에트로피가 됩니다.

\begin{align}H(X)&=-\sum^n_{k=1}p(k)\log_2(p(k))\\\tag{식 2}n:&\,\text{클래스의 수} \\p(k):&\,\text{클래스 k의 확률} \end{align}

다음은 동전던지기 2번, 주사위 6번을 시행한 경우를 계산한 것입니다.

n1=2
p1=1/2
ent1=-np.sum([p1*np.log(p1) for _ in range(n1)])
ent1
0.6931471805599453
n2=6
p2=1/6
ent1=-np.sum([p2*np.log(p2) for _ in range(n2)])
ent1
1.7917594692280547

데이터 셋의 각 샘플의 확률을 알수 있는 경우 scipy.stats.entropy() 메서드를 사용하여 엔트로피를 계산할 수 있습니다.

from scipy.stats import entropy
p=np.repeat(1/6, 6)
ety=entropy(p)
ety
1.791759469228055

엔트로피는 확률이 낮을 수록 높습니다. 즉, 불확실성이 증가할수록 엔트로피는 증가합니다. 다음 그림은 이 관계를 나타내기 위해 확률의 변화에 따른 엔트로피의 변화를 나타낸 것입니다.

def entropyCal(events, ets=1e-15):
    return(-np.sum([p*np.log(p+ets) for p in events]))

probs=np.arange(0.0, 0.6, 0.1)
dist=np.array([[p, 1.0-p] for p in probs])
etys=np.array([entropyCal(d) for d in dist])

plt.figure(figsize=(6, 3))
plt.plot(probs, etys, marker=".")
plt.xticks(probs, [str(d) for d in dist])
plt.xlabel("Change of Probs")
plt.ylabel("Entropy")
plt.show()

위 그림은 모든 샘플의 확률이 동일할 경우 가장 높은 엔트로피를 나타냅니다. 반면에 불확실성이 가장 높은(확률=0) 경우와 가장낮은(확률=1) 경우가 포함된 분포에서 최저의 엔트로피를 보입니다. 그러므로 왜곡된 분포의 엔트로피는 균일 분포에서의 엔트로피보다 낮습니다.

정보획득(Ingformation Gain)

정보획득은 정보를 획득함으로서 감소되는 불확실성을 계산하는 것입니다. 주로 결정트리(decision tree)등의 분류 알고리즘에 사용됩니다. 또한 대상 변수의 이득을 평가하여 그 결과로 특징(feature)를 선택하는 과정에 사용됩니다. 특히 특징의 선택에 사용되는 정보획득을 상호정보(mutual information)이라 합니다.

IG(정보획득)은 식 3과 같이 데이터 세트를 분할함으로써 엔트로피의 감소를 측정하는 것입니다.

\begin{align}\tag{식 3}\text{IG}&=\text{entropy of parent}-\sum^n_i \text{weight}\cdot \text{entropy of child}_i\\ &\text{weight}=\frac{\text{size of child}_i}{\text{size of parent}}\end{align}

다음은 데이터 y를 두그룹으로 분할 한 경우 정보획득(information gain)을 계산한 것입니다.

rndGen=np.random.RandomState(9)
y=rndGen.choice([0, 1], 20)
y
array([0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1])
def probCal(x):
    tot=len(x)
    uni, cnt=np.unique(x, return_counts=True)
    re=pd.DataFrame(cnt/tot, columns=["Probability"])
    return(re)
prob_y=probCal(y)
prob_y
Probability
0 0.55
1 0.45
ety_y=entropy(prob_y); ety_y
array([0.68813881])

위 데이터 y를 두 그룹으로 분류하면 다음과 같습니다.

g1=np.array([0,0,0,0,0,0,0,1])
g2=np.array([0,0,0,0, 1,1,1,1,1,1,1, 1])
ety_g1=entropy(probCal(g1))
ety_g2=entropy(probCal(g2))
print(f"entropy of calss1={ety_g1}\nentropy of calss2={ety_g2}")
entropy of calss1=[0.37677016]
entropy of calss2=[0.63651417]

위 분할된 두 그룹의 엔트로피는 각각의 기대값입니다.

ety_level2=len(g1)/len(y)*ety_g1+len(g2)/len(y)*ety_g2
ety_level2
array([0.53261657])
ig=ety_y-ety_level2
ig
array([0.15552225])

즉, 두 그룹으로 분할후 엔트로피는 감소했습니다. 이것은 불확실성이 감소한 것으로 분할후 확률이 높아짐을 나타냅니다. 결과적으로 동종들 끼리의 모둠 현상이 개선됨을 나타냅니다.

댓글

이 블로그의 인기 게시물

[Linear Algebra] 유사변환(Similarity transformation)

유사변환(Similarity transformation) n×n 차원의 정방 행렬 A, B 그리고 가역 행렬 P 사이에 식 1의 관계가 성립하면 행렬 A와 B는 유사행렬(similarity matrix)이 되며 행렬 A를 가역행렬 P와 B로 분해하는 것을 유사 변환(similarity transformation) 이라고 합니다. $$\tag{1} A = PBP^{-1} \Leftrightarrow P^{-1}AP = B $$ 식 2는 식 1의 양변에 B의 고유값을 고려한 것입니다. \begin{align}\tag{식 2} B - \lambda I &= P^{-1}AP – \lambda P^{-1}P\\ &= P^{-1}(AP – \lambda P)\\ &= P^{-1}(A - \lambda I)P \end{align} 식 2의 행렬식은 식 3과 같이 정리됩니다. \begin{align} &\begin{aligned}\textsf{det}(B - \lambda I ) & = \textsf{det}(P^{-1}(AP – \lambda P))\\ &= \textsf{det}(P^{-1}) \textsf{det}((A – \lambda I)) \textsf{det}(P)\\ &= \textsf{det}(P^{-1}) \textsf{det}(P) \textsf{det}((A – \lambda I))\\ &= \textsf{det}(A – \lambda I)\end{aligned}\\ &\begin{aligned}\because \; \textsf{det}(P^{-1}) \textsf{det}(P) &= \textsf{det}(P^{-1}P)\\ &= \textsf{det}(I)\end{aligned}\end{align} 유사행렬의 특성 유사행렬인 두 정방행렬 A와 B는 'A ~ B' 와 같...

[sympy] Sympy객체의 표현을 위한 함수들

Sympy객체의 표현을 위한 함수들 General simplify(x): 식 x(sympy 객체)를 간단히 정리 합니다. import numpy as np from sympy import * x=symbols("x") a=sin(x)**2+cos(x)**2 a $\sin^{2}{\left(x \right)} + \cos^{2}{\left(x \right)}$ simplify(a) 1 simplify(b) $\frac{x^{3} + x^{2} - x - 1}{x^{2} + 2 x + 1}$ simplify(b) x - 1 c=gamma(x)/gamma(x-2) c $\frac{\Gamma\left(x\right)}{\Gamma\left(x - 2\right)}$ simplify(c) $\displaystyle \left(x - 2\right) \left(x - 1\right)$ 위의 예들 중 객체 c의 감마함수(gamma(x))는 확률분포 등 여러 부분에서 사용되는 표현식으로 다음과 같이 정의 됩니다. 감마함수는 음이 아닌 정수를 제외한 모든 수에서 정의됩니다. 식 1과 같이 자연수에서 감마함수는 factorial(!), 부동소수(양의 실수)인 경우 적분을 적용하여 계산합니다. $$\tag{식 1}\Gamma(n) =\begin{cases}(n-1)!& n:\text{자연수}\\\int^\infty_0x^{n-1}e^{-x}\,dx& n:\text{부동소수}\end{cases}$$ x=symbols('x') gamma(x).subs(x,4) $\displaystyle 6$ factorial 계산은 math.factorial() 함수를 사용할 수 있습니다. import math math.factorial(3) 6 a=gamma(x).subs(x,4.5) a.evalf(3) 11.6 simpilfy() 함수의 알고리즘은 식에서 공통사항을 찾아 정리하...

sympy.solvers로 방정식해 구하기

sympy.solvers로 방정식해 구하기 대수 방정식을 해를 계산하기 위해 다음 함수를 사용합니다. sympy.solvers.solve(f, *symbols, **flags) f=0, 즉 동차방정식에 대해 지정한 변수의 해를 계산 f : 식 또는 함수 symbols: 식의 해를 계산하기 위한 변수, 변수가 하나인 경우는 생략가능(자동으로 인식) flags: 계산 또는 결과의 방식을 지정하기 위한 인수들 dict=True: {x:3, y:1}같이 사전형식, 기본값 = False set=True :{(x,3),(y,1)}같이 집합형식, 기본값 = False ratioal=True : 실수를 유리수로 반환, 기본값 = False positive=True: 해들 중에 양수만을 반환, 기본값 = False 예 $x^2=1$의 해를 결정합니다. solve() 함수에 적용하기 위해서는 다음과 같이 식의 한쪽이 0이 되는 형태인 동차식으로 구성되어야 합니다. $$x^2-1=0$$ import numpy as np from sympy import * x = symbols('x') solve(x**2-1, x) [-1, 1] 위 식은 계산 과정은 다음과 같습니다. $$\begin{aligned}x^2-1=0 \rightarrow (x+1)(x-1)=0 \\ x=1 \; \text{or}\; -1\end{aligned}$$ 예 $x^4=1$의 해를 결정합니다. solve() 함수의 인수 set=True를 지정하였으므로 결과는 집합(set)형으로 반환됩니다. eq=x**4-1 solve(eq, set=True) ([x], {(-1,), (-I,), (1,), (I,)}) 위의 경우 I는 복소수입니다.즉 위 결과의 과정은 다음과 같습니다. $$x^4-1=(x^2+1)(x+1)(x-1)=0 \rightarrow x=\pm \sqrt{-1}, \; \pm 1=\pm i,\; \pm1$$ 실수...