티스토리 뷰
[한글커널] PORTO SEGURO: 운전자 보험 청구 예측 EDA for Korean Part. 1
HONG_YP 2020. 8. 25. 22:38
본 커널은 Porto Seguro의 금메달 EDA 커널을 쉽게 이해하도록 작성한 Korean Starter들을 위한 커널입니다.
대부분의 내용은 이미 공개되어 있는 커널이며 이해하기 쉽게 한글로 번역, 설명을 추가한 커널입니다 참고 부탁드립니다.
본 커널은 비식별 Feature를 사용하는 대회의 EDA를 위한 커널로, 모델링 및 submission은 진행하지 않습니다.
초보자의 입장에서 초보자분들을 위해 커널을 작성하는 만큼, 쉽게 설명하고자 하였습니다.
데이터를 이해함에 있어서 큰 도움을 주신 참고 코드 작성자 분께 감사합니다 :)
금메달 커널 원본: https://www.kaggle.com/bertcarremans/data-preparation-exploration
작성자 커널 원본: https://www.kaggle.com/kongnyooong/porto-eda
< 캐글 커널 원본입니다! 하나의 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
데이터 정보 (데이터를 파악하는 것이 기본, 중요하기 때문에 대회에 나간다면 꼭 확인할 것)
- 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와 시각화를 해보려고 합니다.
그럼 다음 포스팅에서 뵙겠습니다.
감사합니다 :)
'KOREAN 캐글 튜토리얼 프로젝트 > Porto Seguro’s Safe Driver Prediction' 카테고리의 다른 글
[한글커널] PORTO SEGURO: 운전자 보험 청구 예측 EDA for Korean Part. 3 (0) | 2020.10.05 |
---|---|
[한글커널] PORTO SEGURO: 운전자 보험 청구 예측 EDA for Korean Part. 2 (0) | 2020.08.31 |