boot camp day11&12

1112aked·2022년 2월 15일
0

2022/02/14 & 2022/02/15

대회링크

https://dacon.io/competitions/official/235871/overview/description

대회설명

이용 고객의 성별, 나이 등 인적사항과 비행 거리, 지연 시간 등의 정보들을 통해 고객 만족도를 예측하는 대회.

target은 만족(1)/불만족(0)으로 이루어져 있습니다.

Data Analysis

Dacon에서 주최하는 항공사 고객 만족도 예측 경진대회에 KNU-2022 동계 부트캠프 조원들과 함께 출전하게 되었습니다.

항공사 고객 만족도를 머신러닝 학습시키고 target을 맞춰내는 과정을 공유하려고 합니다.
우선은 모듈과 라이브러리들을 추가해주고 data를 읽어줬습니다.

from pycaret.classification import *
from matplotlib import pyplot as plt
import pandas as pd
import numpy as np
import seaborn as sns
%matplotlib inline

import warnings
from pandas.core.common import SettingWithCopyWarning
warnings.simplefilter(action="ignore", category=SettingWithCopyWarning)

data_train = pd.read_csv('/content/drive/MyDrive/airport/train.csv')
data_test = pd.read_csv('/content/drive/MyDrive/airport/test.csv')

다음으로 cat_plot라는 함수를 만들어서 데이터를 시각화하기 쉽게 만들었습니다.

def cat_plot(column):
    f, ax = plt.subplots(1, 3, figsize=(16, 6))
    sns.countplot(x = column,
                data = train,
                ax = ax[0],
                order = train[column].value_counts().index)
    ax[0].tick_params(labelsize=12)
    ax[0].set_title('Full train data')
    ax[0].set_ylabel('count')
    ax[0].tick_params(rotation=50)


    sns.countplot(x = column,
                data = train_1,
                ax = ax[1],
                order = train_1[column].value_counts().index)
    ax[1].tick_params(labelsize=12)
    ax[1].set_title('target = 1')
    ax[1].set_ylabel('count')
    ax[1].tick_params(rotation=50)

    sns.countplot(x = column,
                data = train_0,
                ax = ax[2],
                order = train_0[column].value_counts().index)
    ax[2].tick_params(labelsize=12)
    ax[2].set_title('target = 0')
    ax[2].set_ylabel('count')
    ax[2].tick_params(rotation=50)

    plt.subplots_adjust(wspace=0.3, hspace=0.3)
    plt.show()

위와같이 시각화를 한 후에 데이터를 분석을 해보니 데이터의 종류가 범주형 데이터와 이산형 데이터로 이루어져있었습니다. 그래서 두 데이터를 나누어서 리스트를 만들어줬습니다.
numeric_feature = ['Age', 'Flight Distance', 'Departure Delay in Minutes', 'Arrival Delay in Minutes']
ordinal_feature = ['Seat comfort', 'Departure/Arrival time convenient', 'Food and drink', 'Gate location', 
           'Inflight wifi service', 'Inflight entertainment', 'Online support', 'Ease of Online booking', 
           'On-board service', 'Leg room service', 'Baggage handling', 'Checkin service', 'Cleanliness', 'Online boarding']
categorical_feature = ['Gender', 'Customer Type', 'Type of Travel', 'Class']

또, 이산형 데이터에서 0이라고 표현되어있는 것이 결측치임을 알게되었습니다.
그래서 어떤 컬럼이 결측치가 제일 많은지 보기쉽게 프린트했습니다.

print("Train data missing value")
for feature in ordinal_feature:
    if len(data_train[data_train[feature] == 0]) > 0:
        print(feature, len(data_train[data_train[feature] == 0]))

print("=======================")
        
print("Test data missing value")
for feature in ordinal_feature:
    if len(data_test[data_test[feature] == 0]) > 0:
        print(feature, len(data_test[data_test[feature] == 0]))

이후 train data에만 Ease of Online Booking과 Online boarding의 결측치가 1개 있기 때문에 이 부분은 train data만 간단하게 수정해줍니다. 또, Seat comfort에서 0인 사람들은 모두가 타겟이 1 이었기 때문에 0은 Seat comfort에서 5로 정해도 될 것이라고 판단했습니다.

data_train["Ease of Online booking"][data_train["Ease of Online booking"] == 0] = 3
data_train["Online boarding"][data_train["Online boarding"] == 0] = 3

data_train['Seat comfort'][data_train['Seat comfort'] == 0] = 5
data_test['Seat comfort'][data_test['Seat comfort'] == 0] = 5

이후 그래프에서 봤을 때 고쳐주면 좋을 것 같다고 생각했던 것들을 고쳐주었습니다.

data_train['On-board service'][data_train['On-board service'] == 0] = 4
data_test['On-board service'][data_test['On-board service'] == 0] = 4


# 1,2 항목 병합 필요한 변수들

data_train['Inflight entertainment'][data_train['Inflight entertainment'] == 1] = 2
data_test['Inflight entertainment'][data_test['Inflight entertainment'] == 1] = 2

data_train['Checkin service'][data_train['Checkin service'] == 1] = 2
data_test['Checkin service'][data_test['Checkin service'] == 1] = 2

data_train['Cleanliness'][data_train['Cleanliness'] == 1] = 2
data_test['Cleanliness'][data_test['Cleanliness'] == 1] = 2




# 2,3 항목 변환 필요한 변수들
data_train['Leg room service'][data_train['Leg room service'] == 2] = 3
data_test['Leg room service'][data_test['Leg room service'] == 2] = 3

data_train['Baggage handling'][data_train['Baggage handling'] == 2] = 3
data_train['Baggage handling'][data_train['Baggage handling'] == 0] = 4

data_test['Baggage handling'][data_test['Baggage handling'] == 2] = 3
data_test['Baggage handling'][data_test['Baggage handling'] == 0] = 4


# 조금 특별한 변환 필요한 변수들
data_train['Food and drink'][data_train['Food and drink'] == 1] = -1
data_train['Food and drink'][data_train['Food and drink'] == 2] = 1
data_train['Food and drink'][data_train['Food and drink'] == 3] = 2
data_train['Food and drink'][data_train['Food and drink'] == -1] = 3
data_train['Food and drink'][data_train['Food and drink'] == 0] = 5

data_test['Food and drink'][data_test['Food and drink'] == 1] = -1
data_test['Food and drink'][data_test['Food and drink'] == 2] = 1
data_test['Food and drink'][data_test['Food and drink'] == 3] = 2
data_test['Food and drink'][data_test['Food and drink'] == -1] = 3
data_test['Food and drink'][data_test['Food and drink'] == 0] = 5


전에 시각화에서 얻게 된 정보중에 'Departure Delay in Minutes', 'Arrival Delay in Minutes'
위 두 데이터가 너무 한쪽으로 치우쳐저있었습니다. 그래서 log형변환을 이용하여 치우진 정도를 줄여보았습니다.

data_train['Departure Delay in Minutes'] = np.log1p(data_train['Departure Delay in Minutes'])
data_train['Arrival Delay in Minutes'] = np.log1p(data_train['Arrival Delay in Minutes'])

data_test['Departure Delay in Minutes'] = np.log1p(data_test['Departure Delay in Minutes'])
data_test['Arrival Delay in Minutes'] = np.log1p(data_test['Arrival Delay in Minutes'])

이후 datawig라는 툴을 이용하여 결측치를 대체하는 작업을 해주었습니다.

일단 datawig를 통해 대치하기 위해 0값을 np.nan값으로 바꿔주었습니다.

for i in range(len(data_train)):
    for feature in ordinal_feature:
        if data_train[feature].iloc[i] == 0:
            data_train[feature].iloc[i] = np.nan

for i in range(len(data_test)):
    for feature in ordinal_feature:
        if data_test[feature].iloc[i] == 0:
            data_test[feature].iloc[i] = np.nan

이후 datawig를 이용하여 상관관계가 높은 3개의 feature를 선정하고 학습시킨뒤 train과 test셋의 결측치를 대치합니다.

import datawig
target_feature = "Inflight wifi service"

imputer = datawig.SimpleImputer(input_columns=['Online boarding', 'Ease of Online booking', 'Online support'],
                                output_column=target_feature)
imputer.fit(train_df=data_train, num_epochs=50)

null_train = data_train[data_train[target_feature].isnull()]
null_imputed = imputer.predict(null_train)
imputed_train = pd.DataFrame(null_imputed)

n = 0
for i in range(len(data_train)):
    if np.isnan(data_train[target_feature].iloc[i]) == True:
        data_train[target_feature].iloc[i] = int(round(imputed_train[target_feature+"_imputed"].iloc[n]))
        n += 1
        
null_train = data_test[data_test[target_feature].isnull()]
null_imputed = imputer.predict(null_train)
imputed_train = pd.DataFrame(null_imputed)

n = 0
for i in range(len(data_test)):
    if np.isnan(data_test[target_feature].iloc[i]) == True:
        data_test[target_feature].iloc[i] = int(round(imputed_train[target_feature+"_imputed"].iloc[n]))
        n += 1

target_feature을 'Leg room service'로 바꾼뒤 다시 실행했습니다.

이후 target을 구하는데 필요가 없다고 판단되는 속성을 삭제했습니다.

data_train = data_train.drop(['Gate location','Departure Delay in Minutes', 'Departure/Arrival time convenient', 'id'], axis = 1)
data_test = data_test.drop(['Gate location','Departure Delay in Minutes', 'Departure/Arrival time convenient', 'id'], axis = 1)

이후 pycaret을 이용하여 학습을 시킨뒤

from pycaret.classification import *
clf1 = setup(data = data_train,
             silent = True,
             target = 'target',
             session_id = 20201809,
             n_jobs = 7)
             
best = compare_models(n_select=3, fold = 10) #상위 모델 3개를 선택합니다
blend_3_soft = blend_models(estimator_list=best, method='soft', choose_better = True)
predict_model(blend_3_soft).head(10)
final_blend_3_soft = finalize_model(blend_3_soft)
prediction = predict_model(final_blend_3_soft, data = data_test)

submission = pd.read_csv("/content/drive/MyDrive/airport/sample_submission.csv")

submission['target'] = prediction['Label']

submission.to_csv("flight_predict_test.csv",index=False)

그중 상위 모델 3개를 선택하고 그걸로 예측을 하여 target을 만들어 csv파일로 만들어서 제출하였습니다.

datawig 빼서 실행하면 0.931 나왔습니다.

profile
KNU COMPUTER ENGINEERING

1개의 댓글

comment-user-thumbnail
2022년 2월 15일

아주 나이스

답글 달기