티스토리 뷰

본 커널은 Porto Seguro의 금메달 EDA 커널을 쉽게 이해하도록 작성한 Korean Starter들을 위한 커널입니다.

 

대부분의 내용은 이미 공개되어 있는 커널이며 이해하기 쉽게 한글로 번역, 설명을 추가한 커널입니다 참고 부탁드립니다.

 

본 커널은 비식별 Feature를 사용하는 대회의 EDA를 위한 커널로, 모델링 및 submission은 진행하지 않습니다.

초보자의 입장에서 초보자분들을 위해 커널을 작성하는 만큼, 쉽게 설명하고자 하였습니다.

 

데이터를 이해함에 있어서 큰 도움을 주신 참고 코드 작성자 분께 감사합니다 :)

 

금메달 커널 원본: https://www.kaggle.com/bertcarremans/data-preparation-exploration

 

Data Preparation & Exploration

Explore and run machine learning code with Kaggle Notebooks | Using data from Porto Seguro’s Safe Driver Prediction

www.kaggle.com

작성자 커널 원본: https://www.kaggle.com/kongnyooong/porto-eda

 

Porto 금메달 EDA 커널 리뷰

Explore and run machine learning code with Kaggle Notebooks | Using data from Porto Seguro’s Safe Driver Prediction

www.kaggle.com

< 캐글 커널 원본입니다! 하나의 Upvote가 더 좋은 커널을 만드는 원동력이 됩니다 :) >

대회 정보

  • Porto Seguro는 브라질의 자동차 보험 회사라고 한다.
  • 이 대회의 목적은 어떤 차주가 내년에 보험 청구를 할 확률을 예측하는 것
  • predict_proba라는 함수를 사용해서 값을 예측 (확률 값)
  • 대회의 평가지표는 특이하게 Normalized Gini Coefficient를 사용함
  • Normalized Gini Coefficient를 사용하는 이유:
    Imbalanced Class를 평가를 위한 임계값을 어떻게 정하느냐에 따라 예측값이 바뀜
    = ROC 커브로 확인 (면적으로 스코어를 매김) >> 비슷한 목적으로 Gini Coefficient가 쓰임
    = gini = 2 * AUC - 1
    출처: https://stats.stackexchange.com/questions/306287/why-use-normalized-gini-score-instead-of-auc-as-evaluation
 

Why use Normalized Gini Score instead of AUC as evaluation?

Kaggle's competition Porto Seguro's Safe Driver Prediction uses Normalized Gini Score as evaluation metric and this got me curious about the reasons for this choice. What are the advantages of using

stats.stackexchange.com

데이터 정보 (데이터를 파악하는 것이 기본, 중요하기 때문에 대회에 나간다면 꼭 확인할 것)

  • 59만 개의 train set과 89만 개의 test set으로 구성되어 있음
  • 실제 기업 데이터이기 때문에 feature를 비식별화 해놨음 (그렇기 때문에 난이도가 높은 쪽에 속함)
  • feature들이 그루핑 되어 있음 (비식별화 해놨으니 어떤거에 관련된거다 라고 주어진듯)
    ind: 정수값 매핑
    reg: region(지역관련 변수로 예상)
    car: 차에 관련된 변수
    calc: 실수값 (어떤 값들이 임의로 계산된 값이라고 예상)
  • bin은 binary feature, cat은 categorical feature에 해당
  • 나머지는 그냥 연속형 변수 or 순서형 변수
  • 모든 Null Value는 -1로 대체되어 있음
  • 타겟값은 이전에 보험 청구가 있었으면 1 아니면 0으로 되어있음

Part1. Data Check

# import library

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import warnings

from sklearn.impute import SimpleImputer # 결측치 대체를 위한 라이브러리
from sklearn.preprocessing import PolynomialFeatures # 교호작용 변수 생성 (중요한 변수끼리의 곱)
from sklearn.preprocessing import StandardScaler

from sklearn.feature_selection import VarianceThreshold # FeatureSelection에서 분산이 기준치보다 낮은 feature는 탈락
from sklearn.feature_selection import SelectFromModel # Feature Importance를 제공하는 모델의 importance를 활용하여 변수선택

from sklearn.utils import shuffle
from sklearn.ensemble import RandomForestClassifier

warnings.filterwarnings("ignore")
pd.set_option("display.max_columns", 100)

먼저 사용할 라이브러리들을 불러옵니다. 

 

Imputer가 업데이트 후 SimpleImputer로 이름이 바뀌었다고 합니다. 

결측치 대체를 위한 라이브러리 입니다.

 

다른 라이브러리들은 추후에 사용하는 부분에서 설명하도록 하겠습니다.

 

data_path = "../input/porto-seguro-safe-driver-prediction/"

df_train = pd.read_csv(data_path+"train.csv")
df_test = pd.read_csv(data_path+"test.csv")

데이터를 불러옵니다.

 

porto 대회가 워낙 옛날 대회이다보니 캐글에 있는 커널들은 대부분 예전 방식의 경로로 설정되어 있습니다.

당황하지 마시고 하위 폴더를 확인하신 후 경로를 설정해주시면 됩니다! 

캐글 인터페이스가 바뀐 후 모든 대회들이 하위 폴더가 하나 혹은 몇개씩 더 생겼으므로 path를 지정해주는 것이 편합니다.

 

df_train.head()

df_test.head()

간단하게 train과 test 데이터 셋을 확인하였습니다.

 

print(df_train.shape)
print(df_test.shape)

데이터의 행과 열을 확인해봅니다.

target과 id를 제외한 58개의 feature가 존재합니다.

특이한 점은 train set이 test set보다 적다는 점입니다.

 

df_train.isnull().sum()

train 데이터 셋의 Null Value를 확인해봅니다. 

모든 feature가 0으로 Null Value가 없다고 출력됩니다.

처음 데이터 정보에서 말씀드렸다시피 Porto Seguro 대회의 결측치는 모두 -1로 대체되어 있습니다.

 

이러한 이유로 데이터 정보를 확실하게 알고 가시는게 헤매지 않고 데이터를 정확하게 파악할 수 있습니다! 

 

import missingno as msno # 결측치 시각화 라이브러리

msno.matrix(df=df_train.iloc[:,:40], figsize=(14, 10))

missingno 라이브러리로 시각화도 해봤습니다.

역시나 Null Value가 없이 Matrix가 가득 차 있는 모습입니다.

 

df_train.head()로 알아본 데이터 형식

  • Binary 변수
  • 정수로 이루어진 Categorical 변수 (집값예측과 비슷, 범주형이지만 일단 인코딩이 필요해보이진 않는다.)
  • 나머지 변수는 int와 float로 이루어져 있음
  • Null값은 -1로 이루어져 있으므로 isnull()로 확인되지 않음

Metadata

금메달 상위 커널인 'Data Prepraration&Exploration'은 아래와 같은 방법으로 데이터를 정리해두었습니다.

FE, Visualization에서 편하게 데이터를 사용할 수 있는 꿀팁이라고 생각합니다.

 

  • 데이터의 역할: input, ID, target
  • 데이터의 레벨: nominal, interval, ordinal, binary (명목, 간격, 순서, 이진)
  • 버릴지 안버릴지: True or False (아래의 경우는 id 변수만 버리고 나머지는 가져감)
  • 데이터의 타입: int, float, str
# append를 위해 빈 리스트를 만들어주었음
data = []

for f in df_train.columns:
    # 데이터의 역할을 지정 (독립변수, 종속변수, id (PM))
    if f == 'target':
        role = 'target'
    elif f == 'id':
        role = 'id'
    else:
        role = 'input'
         
    # 데이터의 레벨을 지정 (명목변수, 간격변수, 순서변수등을 레벨이라고 표현한 듯)
    if 'bin' in f or f == 'target':
        level = 'binary'
    elif 'cat' in f or f == 'id':
        level = 'nominal'
    elif df_train[f].dtype == float:
        level = 'interval'
    elif df_train[f].dtype == int:
        level = 'ordinal'
        
    # id는 False로 지정해주어 버리기로 하고, 나머지는 True로 가져감
    keep = True
    if f == 'id':
        keep = False
    
    # 데이터의 타입 지정
    dtype = df_train[f].dtype
    
    # DataFrame으로 만들기 위해 리스트에 append하기 전에 딕셔너리 타입으로 만들어주었음
    f_dict = {
        'varname': f,
        'role': role,
        'level': level,
        'keep': keep,
        'dtype': dtype
    }
    data.append(f_dict)

# 변수의 이름을 인덱스로 하는 데이터프레임을 만들어줌     
meta = pd.DataFrame(data, columns = ["varname", "role", "level", "keep", "dtype"])
meta.set_index("varname", inplace = True)

코드가 굉장히 길지만 사실 별거없이 DataFrame을 만들어주는 코드입니다.

 

먼저 빈 리스트를 만들어주고, train 데이터셋의 column들을 반복문을 활용하여 조건에 맞게 처리하는 코드입니다.

데이터의 레벨 같은 경우는 대회 데이터 특성 상 (이름에 bin, cat 등이 붙어있음) 상세하게 나눌 수 있습니다.

 

완성된 데이터프레임을 살펴보도록 합시다.

meta

모든 feature가 인덱스로 들어가기 때문에 뒷 부분은 생략하였습니다.

 

이렇게 feature 하나하나의 특성을 지정해주어 추후 과정에서 본인이 원하는 조건에 편하게 맞춰서 인덱싱을 할 수 있게 합니다. 

 

위의 방법대로 만들어서 어떤식으로 활용할 수 있는가?

ex1. 버리지 않을 변수중에서 nominal(명목형 변수)만 확인해보고 싶다.

# ex1

meta[(meta["level"] == "nominal") & (meta["keep"])].index


ex2. 각 레벨의 역할과 레벨에 해당하는 변수가 몇개가 있는지 확인해보고 싶다.

# ex2

meta.groupby(["role", "level"])["role"].size()

위와 같은 방식으로 데이터에 대한 정보를 알고싶거나, 혹은 인덱싱이 필요할 때 정말 간편하게 사용할 수 있습니다.

 

제가 다루었던 House Price 커널을 보셨다면 아시겠지만, 데이터의 레벨을 저렇게 상세하게 다루지 않고도 간편하게 연속형/범주형으로 나누어서 사용하기도 합니다.

위의 방식이 복잡하거나 어렵게 느껴지시는 분은 feature들이 연속형인지 혹은 범주형인지만 나누어서 사용하셔도 충분히 편하게 작업을 수행할 수 있습니다.

 

Part. 1 은 여기까지 다뤄보도록 하겠습니다.

 

다음 파트에서는 본격적으로 Feature들에 대한 EDA와 시각화를 해보려고 합니다. 

 

그럼 다음 포스팅에서 뵙겠습니다.

 

감사합니다 :) 

 

반응형
댓글