Information Content
1. 일어날 가능성이 높은 사건은 정보량이 낮고, 반드시 일어나는 사건에는 정보가 없는 것이나 마찬가지
2. 일어날 가능성이 낮은 사건은 정보량이 높음
3. 두개의 독립적 사건이 있을 때, 전체 정보량은 각각의 정보량을 더한 것과 같음
사건 x가 일어날 확률을 P(X = x)라고 할 때 사건의 정보량(information content)
밑이 e인 자연로그를 사용 했을 때 P(x)의 값에 대한 -logP(x)의 그래프
파란공 n개, 빨간공 1개가 있을 때 빨간색 공을 뽑는 사건의 정보량 코드
import numpy as np
import math
import random
# 주머니 속에 들어있는 공의 개수입니다. 숫자를 바꾸면서 실험해보세요!
total = 1000
#---------------#
count = 1 # 실험이 끝날 때까지 꺼낸 공의 개수
# 1부터 total까지의 정수 중에서 하나를 뽑고 total과 같으면 실험 종료
# total=1000인 경우 1~999: blue / 1000: red
while True:
sample = random.randrange(1,total+1)
if sample == total:
break
count += 1
print('number of blue samples: '+str(count-1))
print('information content: '+str(-math.log(1/count)))
#result
number of blue samples: 1689
information content: 7.432483807917119
Entropy
사건 x의 정보량 I(x) 사건이 일어날 확률 P(x)에 의해 결정
확률 변수가 가지는 모든 경우의 수에 대해 정보량을 구하고 평균을 내면 확률 변수의 평균적인 정보량을 구할 수 있음
특정 확률 분포를 따르는 사건들의 정보량 기댓값이 엔트로피
For Discrete Random Variables
이산 확률 변수 X가 x1,x2, xn중 하나의 값을 가질 경우 엔트로피는 각 경우의수가 가지는 정보량에 확률을 곱하고 모두 더한 값
첫번째에 특정 색깔의 공이 뽑힐 확률이 각각 0.4, 0.3, 0.2, 0.1이므로 엔트로피는 약 1.28
두번째 주머니의 엔트로피는 0
주머니에 공 10개가 있고 모두 다른색일 경우 −(0.1log0.1)×10≈2.3로 최대값
엔트로피의 직관적 개념인 무질서 또는 불확실성과 비슷
공의 색깔을 2개로 고정하고 색깔의 비율만 조정할 경우,
파란공 9, 빨간공 1개일때의 엔트로피 0.325
6개, 4개가 있는 경우 0.673
빨강과 파란공이 나올 사건 확률이 균등할수록 엔트로피 증가
동전 던질때 앞면이 나올 확률과 엔트로피
For Continuous Random Variables
X가 연속적인 값을 갖는 연속 확률 변수일 때 유한합 대신 적분의 형태로 정의
연속 확률 변수의 엔트로피를 이산 확률 변수와 구분하여 미분 엔트로피(differential entropy)라고 부르기도 함
Kulback Leibler Divergence
머신러닝의 모델에는 2가지가 존재
우선 결정 모델(discriminative model)은 데이터의 실제 분포를 모델링 하지 않고 결정 경계(decision boundary)만을 학습. 모델의 결과값이 0보다 작을 경우 데이터를 1번 클래스로, 클 경우 2번 클래스로 분류
생성 모델(generative model)은 모델로부터 도출할 수 있는 여러 확률 분포와 베이즈 이론을 이용해 데이터 실제 분포를 간접적으로 모델링함. 생성 모델을 학습시킬 때는 두 확률 분포의 차이가 나타나는 지표가 필요한데 그 예가
클백-라이블러 발산(Kulback Leibler Divergence)
데이터가 따르는 실제 확률 분포P(x), 모델이 나타내는 확률 분포Q(x)라고 할 경우, 두 확률 분포의 클백라이블러 발산은
P(x)를 기준으로 계산된 Q(x)의 평균 정보량, P(x)를 기준으로 계산된 P(x)의 평균 정보량 차이로 정의가 가능
P(x)대신 근사적인 분포 Q(x)를 사용했을 때 발생하는 엔트로피의 변화량을 나타내는 값
연속 확률 변수는
KL divergence는 두 확률 분포의 차이를 나타내는 값이기 때문에 거리 함수와 비슷한 성질을 가지고 있음
KL divergence의 대표적 특성
머신러닝 문제는 두 확률 분포의 차이를 줄여야 하므로 DKL(P∣∣Q)를 최소화 하는 방향으로 모델을 학습
P(x)는 실제 데이터의 분포이므로 우리가 직접 바꿀 수 없고, Q(x)는 바꿀 수 있기 때문에 빨간색 부분을 최소화 하는 문제가 됨, P(x)에 대한 Q(x)의 교차 엔트로피
Cross Entropy
P(x)에 대한 Q(x)의 교차 엔트로피 식을 다시 적으면
KL divergence의 계산식으로부터 엔트로피와 교차 엔트로피, KL divergence사이의 관계식
위의 절차로 보아 정답셋 확률분포 P와 모델의 추론결과 확률분포 Q의 차이 KL divergence를 최소화하는 것이 교차엔트로피를 최소화하는 것이 수학적으로 같음
Cross Entropy Loss
모델이 나타내는 확률 분포와 데이터가 따르는 확률 분포 사이의 차이를 나타내는 함수를 손실 함수(loss function)
데이터가 연속적 값을 가지는 경우 회귀, 이산적인 값을 가지는 분류에서는 로지스틱 함수로 표현
cross entropy의 식
분류 문제에서 데이터 라벨은 one-hot encoding을 통해 표현
클래스 종류가 N가지이며 특정 데이터가 n번재 클래스 속할 때 n번째 원소만 1이고 나머지는 0인 N차원 벡터로
입력 데이터 특성이 모델을 통과하면 출력 레이어의 소프트맥스 함수에 의해 각 클래스에 속할 확률이 계산됨
클래스c1,c2,c3이 존재한 분류 문제에서 데이터의 출력값이 다음과 같을 때
이 결과는
데이터가 실제 2번 클래스에 속할 경우 데이터 확률 분포는
cross entropy를 사용하면 P(x)와 Q(x)의 차이를 다음과 같이 계산 가능
one hot vector로 표현되기 때문에 P(x)와 Q(x)의 차이를 cross entropy로 계산할 경우 계산이 간단
Q(x) 분포가 랜덤하게 생성되었을 때 P(x)를 변형시키면서 cross entropy를 계산해볼 수 있는 코드
import numpy as np
import random
# generate random output
#-----------------#
# can be modified
class_num = 4
#-----------------#
q_vector = []
total = 1
for i in range(class_num-1):
q = random.uniform(0,total)
q_vector.append(round(q,3))
total = total - q
q_vector.append(total)
softmax_output = np.array(q_vector)
print(softmax_output)
P(x)를 생성해 cross entropy 계산해보기
#-----------------#
# can be modified
class_index = 1
#-----------------#
p_vector = np.zeros(class_num)
p_vector[class_index-1] = 1
cross_entropy = -np.sum(np.multiply(p_vector, np.log(softmax_output)))
print('model prediction: '+str(softmax_output))
print('data label: '+str(p_vector))
print('cross entropy: '+str(round(cross_entropy,4)))
Cross Entropy와 Likelihood의 관계
모델 파라미터가 θ일 때 모델이 표현하는 분포는 Q(y|X,θ)로 데이터의 실제분포는 P(y|X)로 나타낼 수 있음
Q(y|X,θ) 는 데이터셋과 파라미터가 주어졌을 때 예측값의 분포이므로 모델의 likelihood와 같음
X와 y는 데이터셋에 의해 결정되는 값이기 때문에 모델의 식이 바뀌어도 변하지 않으며
바꿀 수 있는 부분은 -log Q(y|X,θ)뿐으로 cross entropy 최소화 파라미터 값을 구하는 것은
negative log likelihood를 최소화하는 파라미터를 구하는 것과 같음
Decision Tree와 Entropy
간단한 데이터셋을 기준으로 의사결정나무의 원리 알아보기
- Outlook : 전반적 날씨 (Sunny(맑은), Overcast(구름 낀), Rainy(비 오는))
- Temperature : 기온 정보(섭씨온도)
- Humidity : 습도 정보 (수치형 변수(%), 범주형으로 변환된 경우 (high, normal))
- Wind : 풍량 정보 (TRUE(바람 붊), FALSE(바람 안 붊) )
의사결정트리는 어떤 기준으로 전체 데이터를 나눴을 때 나누기 전보다 엔트로피가 감소하면 정보이득을 얻었다고 보는 관점
- : 전체 사건의 집합
- F : 분류 기준으로 고려되는 속성(feature)의 집합
- : 는 F 에 속하는 속성 (예를 들어 가 Outlook일 때, f는 Sunny, Overcast, Rainy 중 하나가 될 수 있다. )
- S_f : 속성을 가진 의 부분집합
- : 집합 X의 크기(원소의 개수)
- : X라는 사건 집합이 지닌 엔트로피
IG(S,F)는 F라는 분류 기준을 선택했을 때 채택을 통해 얻은 정보 이득의 양
e(S)에 대한 식, 전체 14가지 중 play 9번 no play 5번
F가 Outlook일 때 즉 f가 Sunny, Overcast, Rainy중 하나일 때 엔트로피
이때 정보 이득
이러한 방식으로 가능한 모든 분류기준 F에 대한 정보이득을 계산해서 정보이득이 큰 순서대로 사건을 2등분,
의사결정나무 예제
import pandas as pd
import numpy as np
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn import metrics
import os
csv_path = os.getenv('HOME')+'/aiffel/information_theory/diabetes.csv'
col_names = ['pregnant', 'glucose', 'bp', 'skin', 'insulin', 'bmi', 'pedigree', 'age', 'label']
# load dataset
df = pd.read_csv(csv_path, header=0, names=col_names)
df.head()
# 데이터셋 준비
feature_cols = ['pregnant', 'insulin', 'bmi', 'age', 'glucose', 'bp', 'pedigree']
X = df[feature_cols] # Features
y = df.label # Target variable
# Split dataset into training set and test set
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=1)
#result
Accuracy: 0.670995670995671
# 시각화
from sklearn.tree import export_graphviz
from six import StringIO
from IPython.display import Image
import pydotplus
dot_data = StringIO()
export_graphviz(clf,
out_file=dot_data,
filled=True,
rounded=True,
special_characters=True,
feature_names=feature_cols,
class_names=['0','1'])
graph = pydotplus.graph_from_dot_data(dot_data.getvalue())
graph.write_png('diabetes1.png')
Image(graph.create_png(), retina=True)
정보 이득이 되지 않은 Impurity
# 정보 이득이 되지 않고 남은 Impurity 총량 측정
ccp_path1 = clf.cost_complexity_pruning_path(X_train,y_train)
ccp_path2 = clf.cost_complexity_pruning_path(X_test,y_test)
print(np.mean(ccp_path1.impurities))
print(np.mean(ccp_path2.impurities))
#result
0.15300447927425634
0.14867712053802257
의사결정나무를 3depth까지만 했을 때
clf = DecisionTreeClassifier(criterion="entropy", max_depth=3)
# Train Decision Tree Classifer
clf = clf.fit(X_train, y_train)
#Predict the response for test dataset
y_pred = clf.predict(X_test)
# Model Accuracy, how often is the classifier correct?
print("Accuracy:",metrics.accuracy_score(y_test, y_pred))
#result
Accuracy: 0.7705627705627706
정보이득이 되지 않은 남은 엔트로피 총량
dot_data = StringIO()
export_graphviz(clf,
out_file=dot_data,
filled=True,
rounded=True,
special_characters=True,
feature_names = feature_cols,
class_names=['0','1'])
graph = pydotplus.graph_from_dot_data(dot_data.getvalue())
graph.write_png('diabetes2.png')
Image(graph.create_png(), retina=True)
# 정보이득이 되지 않고 남은 Impurity 총량 측정
ccp_path1 = clf.cost_complexity_pruning_path(X_train,y_train)
ccp_path2 = clf.cost_complexity_pruning_path(X_test,y_test)
print(np.mean(ccp_path1.impurities))
print(np.mean(ccp_path2.impurities))
#result
0.7474881472739515
0.6878691771636323
엔트로피 기준으로는 더 정보이득을 얻을 수 있었지만 분류 기준을 더 세우지 않는 것이 모델의 정확도 향상에 이득.
무한정 기준을 쪼개서 진행하면 overfitting의 결과가 나옴