본문 바로가기
데이터분석과 AI/데이터분석과 AI 문법(Python)

수치형 데이터를 범주형으로 만드는 비닝(Binning)의 세 가지 방법 feat. Xverse

by 우공80 2023. 7. 6.
728x90

비닝

머신러닝 전처리를 하다 보면, 수치형 데이터를 범주형 데이터로 변경하는 경우가 있습니다.
연령을 구간별로 나누거나, 소득 수준을 구간별로 나누거나 하는 것인데요. 이런 작업을 비닝(Binning)이라고 합니다.

종종 이런 작업을 통해 모델의 성능이 개선되곤 합니다.

 

비닝에는 동일 너비 비닝(Equal-Width Binning), 동일 빈도 비닝(Equal-Frequency Binning), 모노토닉 비닝(Monotonic Binning)이 있습니다. 이 3가지에 대해 아래에서 설명드리겠습니다.

 

1. 동일 너비 비닝(Equal-Width Binning)

  • 동일 너비 비닝에서는 변수의 범위를 동일한 너비의 고정된 수의 빈으로 나눕니다.
  • 이 방법을 적용하려면 Bin의 개수와 각 Bin의 너비를 결정해야 합니다.
  • 예를 들어 0에서 100 사이의 값을 가진 변수가 있고 5개의 구간을 생성하려는 경우 각 구간의 너비는 100/5 = 20입니다. 따라서 구간은 0-20, 20-40이 됩니다. , 40-60, 60-80 및 80-100.

아래는 간단한 예제입니다.

import pandas as pd

# Create a sample DataFrame with a numeric column
data = {'Numeric': [10, 20, 25, 40, 50, 60, 70, 85, 95, 100]}
df = pd.DataFrame(data)

# Define the number of bins
num_bins = 5

# Perform equal-width binning
df['EqualWidthBins'] = pd.cut(df['Numeric'], bins=num_bins)

# Print the DataFrame with the equal-width bins
print(df['EqualWidthBins'].value_counts())

Output: 각 구간의 길이가 동일하게 나누어진 것을 볼 수 있습니다.

(82.0, 100.0]    3
(9.91, 28.0]     3
(46.0, 64.0]     2
(64.0, 82.0]     1
(28.0, 46.0]     1
Name: EqualWidthBins, dtype: int64

 

2. 동일 빈도 비닝(Equal-Frequency Binning)

  • 동일 빈도 비닝에서는 각 빈에 동일한 수의 관측치가 포함되도록 변수를 빈으로 나눕니다.
  • 이 방법은 왜곡된 데이터가 있거나 각 빈에 비슷한 수의 샘플이 있는지 확인하려는 경우에 유용합니다.
  • 동일 빈도 비닝을 적용하려면 값을 오름차순으로 정렬한 다음 동일한 크기의 그룹으로 나눕니다.
  • 예를 들어 100개의 관측치가 있고 5개의 구간차원을 만들려는 경우 각 구간차원에는 100/5 = 20개의 관측치가 포함됩니다. 값을 정렬하고 처음 20개를 bin 1에 할당하고 다음 20개를 bin 2에 할당하는 식으로 계속합니다.
import pandas as pd

# Create a sample DataFrame with a numeric column
data = {'Numeric': [10, 20, 25, 40, 50, 60, 70, 85, 95, 100]}
df = pd.DataFrame(data)

# Define the number of bins
num_bins = 5

# Perform equal-frequency binning
df['EqualFreqBins'] = pd.qcut(df['Numeric'], q=num_bins, duplicates='drop')

# Print the DataFrame with the equal-frequency bins
print(df['EqualFreqBins'].value_counts())

Output: 구간의 넓이는 다르며, 각 구간에 분포하는 데이터의 개수가 동일한 것을 보실 수 있습니다.

(87.0, 100.0]    2
(64.0, 87.0]     2
(46.0, 64.0]     2
(24.0, 46.0]     2
(9.999, 24.0]    2
Name: EqualFreqBins, dtype: int64

 

3. 모노토닉 비닝(Monotonic Binning)

  • 모노토닉 비닝은 대상 변수와 관계를 갖는 빈을 만드는 것을 목표로 하는 기술입니다.
  • 이 방법은 수치변수와 목표변수 사이의 비선형 관계를 포착하고자 할 때 유용합니다.
  • 모노토닉 비닝을 수행하려면 일반적으로 각 빈 내 대상 변수의 통계 측정(예: 평균, 중앙값 또는 합계)을 사용하여 빈 레이블을 정의합니다.
  • 의사 결정 트리 기반 비닝 또는 정보 값 기반 비닝과 같은 기술을 사용하여 대상 변수와 단조로운 빈을 만들 수 있습니다.
import pandas as pd

# Create a sample DataFrame with a numeric column and a target column
data = {'Numeric': [10, 20, 25, 40, 50, 60, 70, 85, 95, 100],
        'Target': [0, 0, 1, 1, 1, 0, 0, 1, 1, 1]}
df = pd.DataFrame(data)

# Define the number of bins
num_bins = 5

# Perform monotonic binning using mean of the target variable
df['MonotonicBins'] = pd.cut(df['Numeric'], bins=num_bins)

bin_means = df.groupby('MonotonicBins')['Target'].mean()

df['MonotonicBins'] = df['MonotonicBins'].map(bin_means)

# Print the DataFrame with the monotonic bins
print(df['MonotonicBins'].value_counts())

Output: 모노토닉 비닝은 실질적으로 타겟 변수에 영향을 주도록 구간 화하는 방법입니다.

1.000000    4
0.333333    3
0.500000    2
0.000000    1
Name: MonotonicBins, dtype: int64

4. 타이타닉 예제를 활용한 비닝 방법 테스트

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
from sklearn.preprocessing import LabelEncoder
from xverse.transformer import MonotonicBinning

# Load the Titanic dataset
df = pd.read_csv('train.csv')

# Select relevant columns for prediction
selected_columns = ['Pclass', 'Sex', 'Age', 'Fare', 'Embarked', 'Survived']
df = df[selected_columns].copy()

# Drop rows with missing values
df.dropna(inplace=True)

# Convert categorical variables to numerical using LabelEncoder
categorical_cols = ['Sex', 'Embarked']
label_encoder = LabelEncoder()
for col in categorical_cols:
    df[col] = label_encoder.fit_transform(df[col])

# Define the number of bins
num_bins = 5

# Equal-Width Binning
df_equal_width = df.copy()
df_equal_width.name='df_equal_width'
for feature in ['Age', 'Fare']:
    df_equal_width[feature] = pd.cut(df[feature], bins=num_bins, labels=False)

# Equal-Frequency Binning
df_equal_freq = df.copy()
for feature in ['Age', 'Fare']:
    df_equal_freq[feature] = pd.qcut(df[feature], q=num_bins, duplicates='drop', labels=False)
df_equal_freq.name='df_equal_freq'

# Direct Calculation Monotonic Binning
df_monotonic_direct = df.copy()
for feature in ['Age', 'Fare']:
    bin_edges = pd.cut(df[feature], bins=num_bins, labels=False)
    bin_means = df.groupby(bin_edges)['Survived'].mean()
    df_monotonic_direct[feature] = bin_edges.map(bin_means)
df_monotonic_direct.name='df_monotonic_direct'
    
# Xverse Monotonic Binning
binning_transformer = MonotonicBinning(feature_names=['Age', 'Fare'])
binning_transformer.fit(df.drop('Survived',axis=1),df['Survived'])
df_monotonic_xverse = binning_transformer.transform(df)
df_monotonic_xverse.name='df_monotonic_xverse'

from sklearn.preprocessing import LabelEncoder

le=LabelEncoder()

for column in ['Age','Fare']:
    df_monotonic_xverse[column]=le.fit_transform(df_monotonic_xverse[column])
    

for d in [df_equal_width,df_equal_freq,df_monotonic_direct,df_monotonic_xverse]:
    X=d.drop('Survived', axis=1)
    y=d['Survived']

    # Split the data into training and testing sets
    X_train, X_test, y_train, y_test = train_test_split(X,y, test_size=0.2, random_state=42)

    # Train a logistic regression model
    model = LogisticRegression()
    model.fit(X_train, y_train)

    # Evaluate the model on testing data
    y_pred = model.predict(X_test)
    accuracy = accuracy_score(y_test, y_pred)    
    print(d.name," Accuracy:", accuracy)

Output:

df_equal_width  Accuracy: 0.7832167832167832
df_equal_freq  Accuracy: 0.7762237762237763
df_monotonic_direct  Accuracy: 0.7552447552447552
df_monotonic_xverse  Accuracy: 0.7762237762237763

앞서 배운 예제를 활용하여, 비닝 유형별로 titanic 데이터를 예측해 보았습니다. 모노토닉 비닝에 대해서는 Xverse라는 패키지가 존재하여, Xverse를 활용하는 방법도 추가하였습니다.
필요한 경우, 아래 명령어를 이용하여 설치해서 사용해 보시기 바랍니다.

!pip install xverse

여기서는  동일 너비 비닝 방법이 가장 좋은 성능을 보여주는 것으로 나왔습니다. 하지만, 좀 더 복잡한 수치형 데이터라면 다른 비닝 방법이 더 좋은 성능을 보여줄 수도 있습니다. 

즉, 수치형 변수를 범주화하는 비닝 방법의 선택은 정답이 없으며, 데이터의 특성과 해결하려는 특정 문제에 따라 달라집니다. 세 가지 모두 실험해 보고, 가장 적합한 방법을 찾는 것이 좋습니다.

 

※ 실습에 사용한 titanic 데이터입니다. (출처: https://www.kaggle.com/competitions/titanic/data?select=train.csv) 

 

Titanic - Machine Learning from Disaster | Kaggle

 

www.kaggle.com

train.csv
0.06MB

728x90

댓글