데이터 전처리부터 모델 평가까지의 전체 과정을 포함한 파이프라인 구현[미니프로젝트]

Taixi·2024년 9월 29일

생성형 AI 교육

목록 보기
14/35
post-thumbnail

주제

  • 제목 : ICR - Identifying Age-Related Conditions
  • 미션 : 환자의 건강 상태가 클래스 1이 될 것인지 예측하는 모델.
    • 세 가지 medical conditions 중 한 개 이상일 경우 Class 1
    • 그 외 Class 0
  • 문제유형: 이진분류
  • 평가지표:
    • balanced logarithmic loss
      • log loss : 분류 모델이 예측한 확률값을 로그 변환해서 합한 값을 손실함수로 사용.
        Log Loss=1Ni=1N[yilog(pi)+(1yi)log(1pi)]\text{Log Loss} = - \frac{1}{N} \sum_{i=1}^{N} \left[ y_i \log(p_i) + (1 - y_i) \log(1 - p_i) \right]
      • balanced: 각 클래스가 데이터에서 차지하는 비율에 따라 가중치를 부여하는 방식.

파일 정보

파일 및 필드 설명

train.csv

Id

  • 각 관찰에 대한 고유 식별자입니다.

AB - GL

  • 6개의 익명화된 건강 특성. 모두 숫자형이며
  • EJ는 범주형인 는 제외합니다.

Class

  • 1은 대상자가 세가지 상태 중 하나로 진단 받음, 0은 아님을 나타냄

test.csv

  • 테스트 세트. 목표는 이 세트의 피험자가 두 클래스에 속할 확률을 예측하는 것입니다.

greeks.csv

Alpha

  • 연령 관련 질환이 있는 경우, 해당 질환의 유형을 식별합니다.

A

  • 연령 관련 상태 없음

BDG

  • 연령과 관련된 세 가지 상태

Beta,Gamma,Delta

  • 세가지 실험적 특징

라이브러리 및 패키지 설치

pip install coloramaimport os

import shutil
import subprocess
from collections import defaultdict
from copy import copy
from functools import partial
from itertools import product
from pathlib import Path
import numpy as np
import pandas as pd
import plotly.express as px
import plotly.figure_factory as ff
import plotly.graph_objects as go
import scipy.stats as stats

from colorama import Fore
from colorama import Style
from scipy.cluster.hierarchy import linkage
from scipy.spatial.distance import squareform
from scipy.stats import gaussian_kde
from scipy.stats import probplot
from IPython.core.display import HTML
from plotly.subplots import make_subplots
from xgboost import XGBClassifier
from lightgbm import LGBMClassifier

from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.manifold import TSNE
from sklearn.model_selection import StratifiedKFold
from sklearn.pipeline import make_pipeline
from sklearn.svm import SVC
from sklearn.compose import make_column_selector
from sklearn.compose import make_column_transformer
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import VotingClassifier
from sklearn.feature_selection import f_classif
from sklearn.feature_selection import mutual_info_classif
from sklearn.impute import KNNImputer
from sklearn.impute import SimpleImputer
from sklearn.metrics import accuracy_score
from sklearn.metrics import brier_score_loss
from sklearn.metrics import confusion_matrix
from sklearn.metrics import f1_score
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score
from sklearn.metrics import roc_auc_score
from sklearn.metrics import roc_curve
from sklearn.preprocessing import Binarizer
from sklearn.preprocessing import FunctionTransformer
from sklearn.preprocessing import OrdinalEncoder
from sklearn.preprocessing import PowerTransformer
from sklearn.preprocessing import StandardScaler

# Kaggle 환경 설정, Colorama 라이브러리를 사용한 콘솔 색상 설정, 스타일 지정 

ON_KAGGLE = os.getenv("KAGGLE_KERNEL_RUN_TYPE") is not None

# Colorama settings.
CLR = (Style.BRIGHT + Fore.BLACK) if ON_KAGGLE else (Style.BRIGHT + Fore.WHITE)
RED = Style.BRIGHT + Fore.RED
BLUE = Style.BRIGHT + Fore.BLUE
CYAN = Style.BRIGHT + Fore.CYAN
RESET = Style.RESET_ALL

FONT_COLOR = "#010D36"
BACKGROUND_COLOR = "#F6F5F5"

CELL_HOVER = {  # for row hover use <tr> instead of <td>
    "selector": "td:hover",
    "props": "background-color: #F6F5F5",
}
TEXT_HIGHLIGHT = {
    "selector": "td",
    "props": "color: #FF2079; font-weight: bold",
}
INDEX_NAMES = {
    "selector": ".index_name",
    "props": "font-style: italic; background-color: #010D36; color: #F2F2F0;",
}
HEADERS = {
    "selector": "th:not(.index_name)",
    "props": "font-style: italic; background-color: #010D36; color: #F2F2F0;",
}
DF_STYLE = (INDEX_NAMES, HEADERS, TEXT_HIGHLIGHT)

# Utility functions.
def download_dataset_from_kaggle(user, dataset, directory):
    command = "kaggle datasets download -d "
    filepath = directory / (dataset + ".zip")

    if not filepath.is_file():
        subprocess.run((command + user + "/" + dataset).split())
        filepath.parent.mkdir(parents=True, exist_ok=True)
        shutil.unpack_archive(dataset + ".zip", "data")
        shutil.move(dataset + ".zip", "data")


def download_competition_from_kaggle(competition):
    command = "kaggle competitions download -c "
    filepath = Path("data/" + competition + ".zip")

    if not filepath.is_file():
        subprocess.run((command + competition).split())
        Path("data").mkdir(parents=True, exist_ok=True)
        shutil.unpack_archive(competition + ".zip", "data")
        shutil.move(competition + ".zip", "data")


# Html `code` block highlight.
HTML(
    """
<style>
code {
    background: rgba(58, 90, 129, 0.5) !important;
    border-radius: 4px !important;
    color: #f2f2f0 !important;
}
</style>
"""
)

데이터로드

import pandas as pd
train_path = "/content/train.csv"
test_path = "/content/test.csv"
greeks_path = "/content/greeks.csv"

train = pd.read_csv(train_path, index_col="Id").rename(columns=str.strip)
test = pd.read_csv(test_path, index_col="Id").rename(columns=str.strip)
greeks = pd.read_csv(greeks_path, index_col="Id").rename(columns=str.strip)

간단하게 데이터 살펴보기

DF_STYLE = [
    {'selector': 'th', 'props': [('background-color', 'lightblue')]},
    {'selector': 'td', 'props': [('border', '1px solid black')]}
]

train.head().style.set_table_styles(DF_STYLE).format(precision=3)# 소수점 3자리까지

train.info()
# EJ는 범주형이라서 다른 형태로 데이터가 나타나고 있음

greeks.csv

결측값 시각화 표현

train 데이터셋에서 Class 열을 제외한 수치형 데이터에 대한 통계 요약

EDA

  • 그래프와 같이 데이터가 불균형적이다
  1. 히스토그램, 박스플롯: 데이터 이상치 및 분포 확인

2.Pair Plots & Kernel Density Estimation

  • Pair Plots는 다변량 데이터(여러 변수로 구성된 데이터셋)의 관계를 시각화하는 데 유용한 도구
  • 커널 밀도 추정(KDE, Kernel Density Estimation)은 데이터의 분포를 추정하는 방법

Pair Plot: 피쳐 간 상관관계

  • FD - EH , EH - DU, FD - DU는 비교적 양의 상관관계를 보이고 있으며, 점들이 일정한 패턴을 따르고 있음, 하지만 BZ - BC, DV - AR은 같은 쌍은 데이터가 퍼져 있어 뚜렷한 패턴이 보이지않음

Kernal Density Estimation: 커널 밀도 추정

  • 정규 분포에 가까운 변수(BN, CU, GH)는 데이터가 중심값에 집중되어 있으므로 모델링에서 중요한 역할을 할 수 있습니다.
  • 긴 꼬리 분포(AR, AY, BR, BZ)는 이상값 처리가 필요할 수 있으며, 특히 BZ는 두 클래스 간의 차이가 크므로 주목할 필요가 있습니다.
  • 이중봉형 분포(CW, EL, GL)는 서로 다른 집단을 나타내며, 이러한 변수들은 두 클래스 간의 차이를 설명할 수 있습니다.

정규분포와 비교

  • x축 (Theoretical Quantiles): 이론적으로 정규 분포를 따를 경우의 값
  • y축 (Observed Values): 실제 데이터의 값
  • 빨간 선: 정규 분포를 따르는 경우, 데이터가 이 직선을 따라야 합니다. 이 직선에 데이터가 가까울수록 해당 변수가 정규 분포에 가깝다는 의미
  • R² 값은 데이터가 직선에 얼마나 잘 맞는지를 나타내는 지표로, 1에 가까울수록 데이터가 정규 분포에 더 잘 맞는다는 것을 의미
  • 빨간 선에 가까울수록 정규 분포에 잘 맞고, R² 값이 높을수록 적합성이 높음

Log Transformation (로그 변환):

  • 적용 대상: 오른쪽으로 치우친(right-skewed) 데이터에 유효.
  • 요구 사항: 0 이상의 값만 적용 가능 (음수 값이나 0이 있을 경우 변환할 수 없음).

Square Root Transformation (제곱근 변환):

  • 적용 대상: 로그 변환과 유사하게 오른쪽으로 치우친 데이터에 사용.
  • 요구 사항: 0 이상의 값만 적용 가능.

Square Transformation (제곱 변환):

  • 적용 대상: 왼쪽으로 치우친(left-skewed) 데이터에 유효. 작은 값들을 상대적으로 더 크게 만들어 분포를 조정.

Reciprocal Transformation (역수 변환):

  • 적용 대상: 치우친 데이터 또는 이상값(outliers)이 있는 경우 유효.
  • 요구 사항: 0이 아닌 값만 적용 가능.

Box-Cox Transformation:

  • 적용 대상: 치우친 데이터 또는 이상값이 있는 경우에 유효.
  • 요구 사항: 양수의 값만 적용 가능.

Yeo-Johnson Transformation:

  • 적용 대상: Box-Cox 변환의 확장으로, 양수 및 음수 모두에 적용 가능.

전처리

  • 표준화 처리 : Robust Scaler

  • 불균형 데이터 셋: SMOTE 방법 이용

  • 정규성 개선: Box-Cox

    • BoxCox : 데이터가 정규분포를 따르지 않을 때, 정규성을 개선하기 위해 사용.
      • 머신러닝 모델들은 정규분포를 따르는 데이터에 대해 성능이 좋은 경우가 많다
  • 개선전

  • 개선후

변환 결과가 특히 좋지 않은 변수

  • 데이터 분석

  • 중복된 행에서는 Class 0가 압도적으로 많고 Class 1은 거의 존재하지 않지만, 중복되지 않은 행에서는 Class 1의 비율이 크게 증가합니다. 이는 중복된 데이터Class 0에 매우 편향되어 있다는 것을 의미하며, 모델의 성능이나 데이터 분석 시 주의

  • AR, BZ, DV는 거의 동일한 값을 가지므로 제거

  • AY와 DF는 다른 변수들과 약한 상관관계를 가지므로, 이진화 등 다른 방식으로 처리하거나 유지

범주형 EJ 데이터 분석



  • EJ 변수는 모델이 클래스 1(양성 클래스)을 예측하는 데 중요한 역할

t-SNE (t-Distributed Stochastic Neighbor Embedding)

  • 고차원 데이터를 저차원 공간에 시각화하는 데 주로 사용되는 차원 축소 기법
  • 시각화에 사용하고 모델평가에는 사용하지않음

2차원

3차원

성능평가

  • DU는 세 가지 방법론 모두에서 높은 중요도로 평가되었습니다. 이는 DU 특성이 세 가지 알고리즘에서 공통적으로 중요한 역할을 한다는 것을 의미합니다.
  • 반면, GL은 LDA와 MI에서는 매우 중요한 특성으로 평가되었으나, LGBM에서는 상대적으로 덜 중요하게 평가되었습니다.
  • EJ는 범주형 변수로서, LDA에서 중간 정도의 중요도를 보였고, LGBM에서는 거의 중요하지 않은 특성으로 평가되었습니다. MI에서는 중간 정도로 평가되었습니다.
  1. Linear Discriminant Analysis (LDA): LDA는 모델링 기법입니다. 구체적으로, 분류 알고리즘으로 사용됩니다. 주로 클래스 간 차이를 최대화하는 방향으로 데이터를 분류하는 방식입니다. LDA는 선형 분류에 적합한 방법이며, 분류 문제에서 각 변수의 가중치를 기반으로 특성 중요도를 평가할 수 있습니다.
  2. LGBMClassifier (LightGBM): LightGBM은 부스팅 기반의 결정 트리 모델링 기법입니다. 모델링의 일환으로 데이터를 학습하여 예측을 수행하며, 학습 과정에서 각 변수가 얼마나 자주 트리에서 분할에 기여하는지, 또는 정보 이득을 통해 특성 중요도를 평가합니다. 모델링뿐만 아니라 특성 중요도를 계산하는 데도 활용됩니다.
  3. mutual_info_classif(): mutual_info_classif()는 모델링 기법이라기보다는 특성 중요도 평가 방법에 가깝습니다. 이는 특성과 목표 변수 간의 상호 의존성을 계산하는 함수로, 특정한 예측 모델을 학습하는 것이 아니라 특성 선택(Feature Selection)의 도구로 사용됩니다. 이 방법은 비선형 관계까지 포착할 수 있는 평가 도구입니다. 이를 통해 모델링 전에 변수의 유용성을 평가할 수 있습니다.

모델

  • 랜덤 포레스트
  • XGBoost
  • LightGBM
  • Logistic Regression

튜닝 전 Balanced Log Loss

튜닝 없이 앙상블(모델 결합)한 경우

  • XGBoost + LightGBM + SVC : Ensemble, Voting 방법 이용.
    • 가중치:
      • XGBoost: 0.45,
      • LightGBM: 0.45,
      • SVC: 0.10
    • Balanced Log Loss: 0.21858
    • ROC-AUC: 0.97
    • F1 Score: 0.78
    • Random Forest
      • Balanced Log Loss: 0.23094
        • 0에 가까울 수록 좋기에 Randmo Forest 추가가 어떤 좋은 결과를 내진 않았다.

랜덤 포레스트(RandomForestClassifier), 서포트 벡터 머신(SVC)LightGBM(LGBMClassifier) 를 사용해 특성 중요도(Feature Importance)를 평가하는 Permutation Test를 구현한 것입니다. 이 과정의 주요 목적은 balanced log loss를 평가 지표로 삼아, 각 분류기 모델이 특정 특성(피처)을 섞어(shuffle) 학습했을 때 성능에 미치는 영향을 평가하는 것

결과

x축: Balanced Log Loss

y축: 각 특성의 이름

  • DU 특성은 세 모델 모두에서 가장 중요한 특성으로 일관되게 나타납니다.
  • GL, AB, FL 같은 특성들도 각 모델에서 중요한 역할을 하고 있습니다.
  • DU와 같은 중요한 특성들을 중심으로, 특성 선택(feature selection)을 통해 데이터의 차원을 줄이고 모델 성능을 개선
  • Permutation Test를 통해 모델 성능에 가장 중요한 변수들을 식별하고, 불필요한 변수를 제거하여 최종 모델의 성능을 최적화

범주형 Greeks 메타데이터를 분석하고, 병렬 좌표 그래프를 통해 범주 간의 연결성을 시각적으로 탐구

설명

  • Alpha는 연령과 관련된 질환 유형을 나타내는 변수이며, 그래프에서 Alpha의 값이 'A'인 경우는 연령 관련 상태가 없는 사람을 의미하며, 'B', 'D', 'G' 값은 연령과 관련된 질환을 나타냅니다.
  • Alpha가 'G인 경우 주로 Class 1과 연결되고, Alpha가 'A인 경우 Class 0과 강하게 연결됩니다. 이는 Alpha 값이 특정 질환과 타깃 클래스 간에 중요한 연관성을 가지고 있음을 나타냄.

  • Beta = A, Delta = A 조합은 Class 1과 강하게 연관되어 있어, 이 그룹의 사람들이 연령 관련 질환을 가지고 있음
  • Beta = C, Delta = B와 같은 조합은 Class 0과 강하게 연관되어 있어, 이 그룹은 연령 관련 질환이 없거나 상대적으로 적은 상태
  • 전반적으로, BetaDelta의 조합에 따라 Class 1에 속할 가능성이 크게 달라지는 것을 볼 수 있음
  • 2015년부터 2018년 사이의 급격한 Class 1 증가와 2018년 이후의 급격한 감소는 중요한 트렌드

모델 평가

튜닝 방법:

  • RandomizedSearchCV

튜닝 전

  • Logistic Regression 이 더 우수한 성능을 보임
    • 조건: 오버샘플링(SMOTE), 표준화(Robust Scaler) 처리

튜닝 후

  • 위와 같은 조건 하에서 하이퍼 파라미터 튜닝한 XGBoost가 가장 높은 성능을 보인다.
  • 모델들을 섞은 것이 단일 모형에 튜닝을 한 것보다 더 나은 점수가 나오는 경향이 있다.
  • X + L + S + R > XGB_T > LogReg
  • 확장 실험
    - XGBoost + Light GBM + SVC + RandomForest , BLL: 0.23094
  • 조건: 언더샘플링, Stratified K-Fold (계층 분할), Voting, 가중치는 아래와 같다.
XGBoostLightGBMSVCRandomForest
가중치0.350.350.150.15
원저자0.450.450.1

모델 평가 점수

  • 모델이 단순히 XGBoost나 Random Forest 같은 트리 기반 알고리즘으로는 충분하지 않다는 것이 명확해집니다. 이러한 알고리즘들은 특정 중요한 샘플들에 대해 제대로 예측하지 못하는 경우가 있으며, 이 때문에 추가적인 특성 엔지니어링이나 다른 알고리즘을 도입할 필요함

  • 전체적으로, 모델은 양성 클래스를 잘 예측하고 있으며, ROC 곡선에서 높은 성능을 보여주고 있으며, 음성 클래스를 양성으로 예측한 False Positive(48개)가 다소 높은 편이므로, 이러한 부분을 개선할 필요가 있음
profile
개발자를 위한 첫시작

0개의 댓글