Doby's Lab

Kaggle - Learn Feature Engineering : Mutual Information 본문

Data Science/Feature Engineering

Kaggle - Learn Feature Engineering : Mutual Information

도비(Doby) 2022. 10. 10. 16:50

[이 글은 Kaggle의 Learn을 토대로 작성되었습니다. 문제가 될 시 삭제 조치하겠습니다.]
(오역되어 잘못 설명된 부분이 있을 수 있습니다.)
https://www.kaggle.com/code/ryanholbrook/mutual-information

Mutual Information

Explore and run machine learning code with Kaggle Notebooks | Using data from FE Course Data

www.kaggle.com

Intro

Kaggle을 시작하면서 모델을 다루는 능력과 더불어 데이터 분석, EDA, Feature Engineering에 대한 능력 또한 중요하다는 것을 알게 되었습니다. 이를 알고, 구글링 하여 자료를 찾아다녔지만 '중요하다!'라는 말이 많고, 실질적인 내용을 다루는 포스팅은 드물었습니다. Kaggle의 Learn이라는 플랫폼을 알게 되어 기초적인 Feature Engineering을 공부하게 되었습니다. Kaggle 자체가 세계적인 플랫폼이다 보니 전부 영어로 이루어져서 읽는 데에 어려움을 겪고 있습니다. 하지만, 언젠가는 필요했던 영어 독해 능력을 이 참에 길러보자는 생각으로 반복적인 회독을 마친 뒤에 포스팅을 통해 요약정리를 하려 합니다.


Category

  • Introduction
  • Matual Information and What it Measures
  • Interpreting Mutual Information Scores
  • Example - 1985 Automobiles

Introduction

처음으로 방대한 양의 데이터셋의 맞닥뜨리면 보통 어떤 작업부터 해야 할지 감이 오질 않습니다. Description을 읽으면서 feature에 대한 설명을 보아도 감이 잡히지 않는 경우가 많습니다. 이런 상황에서 feature utility metric(feature와 target 간의 관계를 측정하는 function)을 사용하여 더 유용한 feature들을 골라낼 수 있습니다.

해당 feature utility metric을 Mutual Information이라 부릅니다. Mutual Information은 feature와 target 간의 관계를 측정한다는 것에 있어서 correaltion과 많이 닮아 있지만 차이점이 존재합니다. Mutual Information은 어떤 종류의 관계든 모두 측정할 수 있지만, correlation은 선형적인 관계(Linear Relationship)만 측정할 수 있다는 것이 차이점이자 Mutual Information의 이점입니다.

Mutual Information은 범용적으로 많이 쓰이며 아직 어떤 모델을 쓸지 결정을 못 했을 때도 유용한 metric입니다. 그것 외에도 사용하기 쉽고, 효율적인 컴퓨팅 계산, 이론적인 근거 충분(well-founded), Overfitting 억제 등과 같은 장점들이 존재합니다.


Mutual Information and What it Measures

MI(Mutual Information)은 uncertainty(불확실성, = entropy in Information Theory)의 관점에서 관계를 설명합니다. 한 변수가 다른 변수에 대해 어느 정도로 uncertainty를 줄여주는지에 대해 측정하는 것이 MI입니다.

위 figure는 'Ames Housing' 데이터셋에서 가져온 예시로 ExterQual에 따른 SalePrice를 보고 있습니다.
ExterQual의 각 value가 SalePrice에 대해 특정 범위 내에서 집중되어 있는 것을 볼 수 있습니다. 그러면 ExterQual과 SalePrice가 가지는 MI Score는 확실히 ExterQual의 4가지 value를 가져옴으로써 SalePrice의 uncertainty를 줄일 수 있습니다. 그리고, Fair의 빈도가 Typical이나 Good 등 타 변수에 비해 빈도가 적어 보입니다. 이러한 경우 MI Score에 있어 Fair는 작은 영향을 미칠 것입니다.


Interpreting Mutual Information Scores

MI Score가 가질 수 있는 가장 작은 값은 0.0입니다. MI Score가 0일 때는 '두 변수가 서로 독립적이다'라는 것을 말하며 두 feature에 대해 말 할 수 있는 것이 없습니다. 반대로 가장 큰 값은 이론적인 관점에서는 한계가 없습니다. 실제로는 2.0 이상을 넘어가는 경우가 드뭅니다.

위 figure는 다음을 설명합니다.

  • Left: feature와 target간의 의존성에 따른 MI Score 증가
  • Right: Linear relationship뿐만이 아닌 다른 relationship까지 모두 알 수 있는 MI


Mutual Information을 사용하기 전에 기억할 것

  • MI는 target을 예측하는 feature와의 relative potential을 이해하는 데 있어 도움을 줍니다.
  • feature가 다른 feature와 상호 작용할 때 매우 유용할 수 있지만 단독적으로는 유용할 수 없습니다. 그리고, feature 간의 MI를 측정할 수는 없습니다.
  • feature의 실질적인 유용함은 사용하는 모델에 따라 달라집니다.
  • feature는 target과의 관계가 모델이 학습할 수 있는 경우에 유용합니다.
  • MI Score가 높다고해서 모델이 해당 feature를 사용하여 모든 걸 할 수는 없습니다.
  • MI Score를 사용하기 전에도 target과의 관계를 측정할 수 있게 feature를 transform을 해야 하는 경우가 생깁니다.

Example - 1985 Automobiles

Automobile dataset을 통해 MI Score 실습을 해봤습니다. 23가지의 feature가 있고, 이를 기반으로 차량 가격을 측정하는 회귀 문제입니다.

사이킷런에서 제공하는 MI 알고리즘은 Discrete Feature(dtype=int)와 Continuous Feature(dtype=float)를 다르게 처리하기 때문에 이를 구분해주는 discrete_features라는 Boolean Array를 만들어주어 함수(mutual_info_regression)에 알려줍니다.

그리고, categorical data(categorical, object)도 pandas에서 제공하는 factorize()를 통해 encoding을 합니다.

특정 class로 분류하는 것이 아닌 어떤 값을 내놓는 regression이기 때문에 mutual_info_classification이 아닌 mutual_info_regression을 사용합니다.

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.feature_selection import mutual_info_regression # Mutual Information

df = pd.read_csv("../input/fe-course-data/ames.csv")

def make_mi_scores(X, y):
    X = X.copy()
    for colname in X.select_dtypes(["object", "category"]): # object, category만 factorize
        X[colname], _ = X[colname].factorize() # [object, category] to int
    discrete_features = [pd.api.types.is_integer_dtype(t) for t in X.dtypes]
    mi_scores = mutual_info_regression(X, y, discrete_features=discrete_features)
    mi_scores = pd.Series(mi_scores, name='MI Scores', index=X.columns)
    mi_scores.sort_values(ascending=False, inplace=True)
    return mi_scores
        
X = df.copy()
y = X.pop('SalePrice')

temp = make_mi_scores(X, y)
print(temp)

[output]

feature별로 MI Score를 출력해보았습니다. 해당 MI Score들을 Matplotlib을 통해 시각화해봅시다.

def plot_mi_scores(scores):
    scores = scores.sort_values(ascending=True)
    width = np.arange(len(scores))
    ticks = list(scores.index)
    plt.barh(width, scores)
    plt.yticks(width, ticks)
    plt.title('Mutual Information Scores')

plt.figure(dpi=100, figsize=(8, 12))
plot_mi_scores(mi_scores)

[output]

해당 Dataset에는 존재하지 않았지만 예시에서 다룬 Dataset에서 fuel_type이라는 feature가 있습니다. 해당 feature는 MI Score는 낮았지만 아래 figure를 봅시다.

sns.lmplot(x="horsepower", y="price", hue="fuel_type", data=df);

MI Score는 낮지만 figure에서 보이듯이 horsepower feature 내에서 다른 추세를 가진 두 가격 모집단을 명확하게 구분합니다. 즉, fuel_type은 MI Score가 낮다고 해서 중요하지 않은 것이 아니라 interaction effect를 가지는 것을 알 수 있습니다. 그렇기 때문에 MI Score로 판단하기 전, 가능한 interaction effect를 조사해보는 게 좋습니다. 또한 이러한 점에서 도메인 지식은 데이터에 대해 보다 넓은 인사이트를 제공하기도 합니다.

728x90