«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
Recent Posts
Today
Total
관리 메뉴

짜리몽땅 매거진

[ML] 데이터 변환 본문

Data/Machine Learning

[ML] 데이터 변환

쿡국 2024. 8. 19. 17:35

데이터 변환은 데이터를 다른 형태로 바꾸는 작업을 의미합니다. 데이터 변환은 다양한 목적을 가지며, 주로 아래와 같은 이유로 수행하게 된다.

  • 데이터 분포 변화: 데이터가 정규분포를 따르지 않을 때, 로그 변환, 제곱근 변환 등으로 데이터를 변환하여 정규분포에 더 가깝게 만든다. 이 과정을 통해 모델의 성능을 향상시킬 수 있다.
  • 이상치 영향 줄이기: 로그 변환과 같은 방법은 이상치=의 영향을 줄여서 모델이 이상치에 덜 민감하게 만든다.
  • 데이터 관계를 선형화: 비선형적인 관계를 선형으로 바꾸기 위해 데이터 변환이 사용된다. 예를 들어, 지수적인 증가를 보이는 데이터를 로그 변환을 통해 선형화할 있다.

모델링을 진행할 때 성능을 향상시키기 위해 변환과 스케일링 처리를 동시에 수행하는 경우가 많은데 이 두 개의 과정은 차이가 있다.

데이터 변환 데이터 스케일링
데이터의 분포를 조정하는 작업 데이터의 크기를 조정하는 작업
Box-Cox, Yeojohnson, Quantitle, Log transform 등 MinMax, Standard, Robust Scaling 등

 

오늘은 사이킷런에서 제공하는 california_housing 샘플 데이터셋을 데이터 변환을 통해 간단한 선형 회귀모델링을 진행하나 후, 성능이 향상했는지 확인해보자.


1. 필요 라이브러리 import 및 데이터 준비

import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.datasets import fetch_california_housing
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, make_scorer
from sklearn.model_selection import train_test_split, cross_val_score

# 데이터 로드
california = fetch_california_housing()
X = pd.DataFrame(california.data, columns=california.feature_names)
y = pd.Series(california.target)

 

2. 모델링 진행(아직 변환을 하지 않은 상태)

 

데이터 변환 처리를 하지 않은 상태에서 선형 회귀모델의 MSE값은 0.5290이 나온 것을 확인할 수 있다.

 

#학습 데이터셋 테스트로 분리
X_train, X_test, y_train, y_test = train_test_split(X,y, test_size=0.2, random_state=0)

#Lienar Regression
linear_reg = LinearRegression()
linear_reg.fit(X_train, y_train)
y_pred_linear = linear_reg.predict(X_test)
mse_linear = mean_squared_error(y_test, y_pred_linear)
print(f'Linear Regression MSE :{mse_linear:.4f}')

#MSE : 0.5290

 

3. 데이터 분포 확인

시각화를 통해 데이터의 분포를 확인하고, 변수별 왜도와 첨도를 계산해 위도, 경도 변수를 제외한 칼럼은 정규분포 형태로 변환 처리를 진행한다.

def plot_distribution(df, cols, n_cols=3):
    n_rows = (len(cols)+n_cols-1)//n_cols
    fig, axes = plt.subplots(n_rows, n_cols, figsize=(20,4*n_rows))
    for i, col in enumerate(cols):
        row, col_idx = divmod(i, n_cols)
        sns.histplot(df[col], kde=True, ax =axes[row, col_idx])
        axes[row, col_idx].set_title(f'Distribution of {col}')
    plt.tight_layout()
    plt.show()
    
plot_distribution(X, X.columns.tolist())

 

from scipy.stats import skew, kurtosis

# 각 변수의 왜도와 첨도 계산
skewness = X.apply(skew).rename('Skewness')
kurt = X.apply(kurtosis).rename('Kurtosis')
stats = pd.concat([skewness,kurt], axis=1)
print(stats)

 

4. 데이터 변환

여러 데이터 변환 기법 중 Box-Cox 변환, Yeojohnson 변환, QunatitleTransformer 변환을 수행한다.

from sklearn.preprocessing import PowerTransformer, QuantileTransformer

#Box-Cox 변환(양수만 가능)
boxcox_transformer =PowerTransformer(method='box-cox')
X_boxcox=X.copy()
#위도, 경도는 제외하고 나머지 변수는 box-cox변환
for col in X.columns:
    if col not in ['Latitude', 'Longitude'] and (X[col]>0).all():
        X_boxcox[col]=boxcox_transformer.fit_transform(X[[col]])
        
#Yeo-Johnson 변환(양수, 음수 모두 가능)
yeojohnson_transformer =PowerTransformer(method='yeo-johnson')
X_yeojohnson=X.copy()
#위도, 경도는 제외하고 나머지 변수는 Yeo-Johnson변환
for col in X.columns:
    if col not in ['Latitude', 'Longitude']:
        X_yeojohnson[col]=yeojohnson_transformer.fit_transform(X[[col]])

        
#QuantileTransformer(양수, 음수 모두 가능)
quantitle_transformer = QuantileTransformer(output_distribution='normal')
X_quantitle=X.copy()
#위도 경도 제외하고 나머지 변수 quantitle
for col in X.columns:
    if col not in ['Latitude', 'Longitude']:
        X_quantitle[col]=quantitle_transformer.fit_transform(X[[col]])

 

5. 모델링 진행(데이터 변환 처리 후)

이전과 다르게 변환된 데이터로 다시 모델링을 진행한다. 그 결과, 모델의 MSE값이 줄어들어 성능이 향상한 것을 확인할 수 있다.

# 함수를 사용해서 모델 학습 및 성능 출력
def evaluate_model(X,y):
    X_train, X_test, y_train, y_test = train_test_split(X,y, test_size=0.2, random_state=0)
    model = LinearRegression()
    model.fit(X_train, y_train)
    y_pred = model.predict(X_test)
    mse = mean_squared_error(y_test, y_pred)
    return mse
    
#원본데이터(변환X)
mse_original=evaluate_model(X,y)
print(f'mse_original : {mse_original:.4f}')
# 성능 : 0.5290

#Box-Cox
mse_X_boxcox=evaluate_model(X_boxcox,y)
print(f'mse_original : {mse_X_boxcox:.4f}')
# 성능 : 0.5097

#yeojohnson
mse_X_yeojohnson=evaluate_model(X_yeojohnson,y)
print(f'mse_original : {mse_X_yeojohnson:.4f}')
# 성능 : 0.5100

#quantitle
mse_X_quantitle=evaluate_model(X_quantitle,y)
print(f'mse_original : {mse_X_quantitle:.4f}')
# 성능 : 0.5134