【Kaggle入門ー二値分類】Spaceship Titanic-EDA、データ前処理、パラメータ、提出

※アフィリエイト広告を利用しています。

はじめに

Kaggleは、英語のページしかありません。そこで、日本語で読みたい方向けに記事を作成しました。

Spaceship Titanicの概要の説明が前の記事で済みました。

実際にGoogle Colabを動かしてみましょう!

データのインポート

必要なものをインポートします。

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

import warnings
warnings.filterwarnings('ignore')
%matplotlib inline

ドライブをマウントしてください。

from google.colab import drive
drive.mount('/content/drive')

そして、データをインポートします。

train = pd.read_csv('/content/drive/MyDrive/kaggle/Spaceship Titanic/train.csv')
test = pd.read_csv('/content/drive/MyDrive/kaggle/Spaceship Titanic/test.csv')

注意‘/kaggle/Spaceship Titanic/train.csv’←の部分はドライブのフォルダ構成によって内容が異なるので注意してください。

EDA

データの傾向や特徴を確認するために、EDA(Explanatory Data Analysis)を行います。

目的変数であるTransportedそのほかの変数との関係をみてみます。

sns.set_theme(style="darkgrid")
sns.countplot(x="HomePlanet", hue="Transported",data=train)

TransportedHomeplanetとの関係をみてみます。

EuropeとEarthで結果が逆であることがわかります。HomeplanetによってTransportedの結果に少しは影響を与えそうです。

次に、TransportedCryoSleep(仮死状態に置かれていた)との関係をみてみます。

CryoSleep(仮死状態に置かれていた)状態だと、Transportedに成功している数が多いです。

一方、そうじゃないとTransportedに失敗している数が多いです。つまり、TransportedCryoSleepには相関関係がありそうです。

TransportedDestination(乗客が降りる惑星)との関係をみてみます。

sns.set_theme(style="darkgrid")
sns.countplot(x="Destination", hue="Transported",data=train)

TRAPPIST-1eと55 cancri eで結果が逆であることがわかります。

ただ、目的変数であるTransportedとの関連は薄そうです。

次は、TransportedVIPとの関係をみてみます。

sns.set_theme(style="darkgrid")
sns.countplot(x="VIP", hue="Transported",data=train)

VIP料金を払ったからといって、特にTransportedへの結果への影響は少なそうです。

そのほかの数値のカラムとTransportedの相関関係も調べてみます。

train.corr()

0.5を超えるものがないですし、どれも影響が低そうです。

ただ、モデルによっては、影響を与えるものがあるかもしれませんでの、今回は影響の低いものもそのまま残しておきます。

データの前処理-one_hot encoding

目的変数を分けます。

train_x = train.drop(['Transported'],axis=1)
train_y = train['Transported']

テストデータを読み込みます。

test_x = test.copy()

さきほど調べ目的変数と関連のないカテゴリ変数や目的変数と関連のないもの等を学習データとテストデータから外します。

train_x = train_x.drop(['PassengerId', 'Cabin', 'Destination', 'VIP','Name'],axis=1)
test_x = test_x.drop(['PassengerId', 'Cabin', 'Destination',
       'VIP', 'Name'],axis=1)

目的変数と関連があるカテゴリ変数、今回は、‘HomePlanet’‘CryoSleep’one_hot encodingします。

カテゴリ変数とは、文字列型のようにそのままでは、モデルに用いることができず、変換が必要な変数です。

なお、変数が数値であっても、値の大きさや順序に意味がないものは、カテゴリ変数として扱うことも考えられます。

そして、one_hot encodingとは、カテゴリ変数に対して、0,1を用いて数字に変換します。

この変換したものは、ダミー変数と呼ばれ、pandasのget_dummies()で変換可能です。

HomePlanet_get = pd.get_dummies(train_x['HomePlanet'])
CryoSleep_get = pd.get_dummies(train_x['CryoSleep'])

このダミー変数を学習データに結合します。

train_x = pd.concat([train_x,HomePlanet_get],axis=1).drop(columns=['HomePlanet'])
train_x = pd.concat([train_x,CryoSleep_get],axis=1).drop(columns=['CryoSleep'])

同じ処理をテストデータでも行います。

HomePlanet_get = pd.get_dummies(test_x['HomePlanet'])
CryoSleep_get = pd.get_dummies(test_x['CryoSleep'])
test_x = pd.concat([test_x,HomePlanet_get],axis=1).drop(columns=['HomePlanet'])
test_x = pd.concat([test_x,CryoSleep_get],axis=1).drop(columns=['CryoSleep'])

バリデーション

train_test_split()を使って、学習データの精度を図るためにtrain_x,_train_y(‘Transported’)バリデーションしていきます。

今回は、test_size=0.3、つまり3割をテストデータとして、7割を学習データとして用います。

なぜ、バリデーションをするのかというと、自身が構築した特徴量やモデルの予測精度を図るためです。

つまり、バリデーションデータで予測し、その予測の精度を何らかの評価指標でみることで、その特徴量やモデルを用いた場合の精度を図ります

そして、バリデーションデータを用いた中で一番高い精度のものを用いて、実際のデータを予測すれば、精度の高い予測をすることが可能になります。

from sklearn.model_selection import train_test_split
train_x2,val_x,train_y2,val_y = train_test_split(train_x,train_y,test_size=0.3,random_state=0)

モデルの作成・学習

今回は、分類の問題なので、XGBClassifierを用います。XGboostの中で分類で用いるモデルです。

XGBoostは、高効率、柔軟性、移植性に優れた最適化された分散型勾配ブースティング・ライブラリでKaggleで人気のモデルです

from xgboost import XGBClassifier 
model = XGBClassifier(n_estimators=20,random_state=0)
model.fit(train_x2,train_y2)

バリデーションデータの予測精度を見てみましょう。

今回のコンペの評価指標は、Accuracyなので、accuracy_score()で計算できます。

また、Accuracyでは、その後の特徴量の追加やモデルのパラメータ調整による改善を完全にはとらえきれないため、あわせてLoglossも出力します。

Loglossは、分類問題での代表的な評価指標で、予測確率で計算され、その確率が外れているほど高いペナルティが与えられ、低いほどよいものです。

from sklearn.metrics import accuracy_score,log_loss

まずは、Accuracyで用いる予測をします。

va_pred_ac = model.predict(val_x)

次に、Log_lossで用いる予測をします。Log_lossは前述のように予測確率を用いるので、predict_proba()を用います。

va_pred_log = model.predict_proba(val_x)[:,1]

精度をプリントしてみます。

print(f'accuracy_score:{accuracy_score(val_y,va_pred_ac)}')
print(f'log_loss_score:{log_loss(val_y,va_pred_log)}')

パラメータ調整ーグリッドサーチ

より良い精度を目指すために、モデルのパラメータを調整します。

今回は、グリッドサーチを使用します。

グリッドサーチとは、候補のパラメータに対して、それらの組み合わせをすべて計算する方法です。

探索する候補は、自分で設定する必要があります。

つまり、どのパラメータ候補がよいかは、良い予測を出したパラメータをもとに探索するため、モデルの使用経験等がない人やあんまりよい予測モデルを出さなかったパラメータしか手元にない方にはあまりオススメはできません。

また、組み合わせをすべて計算するため、組み合わせが多いと計算時間がかかります。

もっとも、実装は簡単なので、今回は、こちらを用います。

まずは、グリッドサーチをする範囲を設定します。

from sklearn.model_selection import GridSearchCV
estimator = XGBClassifier(random_state=0)

param_grid = [{
    'n_estimators': [10, 20, 30, 50, 100, 300],    
    'max_features': ['sqrt', 'log2','auto', None],  
    'max_depth':    [10, 20, 30, 40, 50, None],     
    'random_state': [0]
 }]

tuned_model = GridSearchCV(estimator=estimator,param_grid=param_grid,cv=5,return_train_score=False)

設定した範囲で、モデルに学習させます。

tuned_model.fit(train_x2,train_y2)

その結果、以下のコードでみることができます。

pd.DataFrame(tuned_model.cv_results_).T

上のでは、わかりずらいので、ベストパラメータをプリントしてみます。

print("最良パラメータ: {}".format(tuned_model.best_params_))

このパラメータで再度検証してみましょう。

まず、グリッドサーチのベストパラメータを取り出したモデルを作成します。

best_model = tuned_model.best_estimator_

このモデルで予測します。

va_pred_ac_best = best_model.predict(val_x)
va_pred_log_best = best_model.predict_proba(val_x)[:,1]

予測結果をプリントします。

print(f'accuracy_score:{accuracy_score(val_y,va_pred_ac_best)}')
print(f'log_loss_score:{log_loss(val_y,va_pred_log_best)}')

先ほどの結果下部のものですが、比べてみるとグリッドサーチで探索したベストパラメータの方がaccuracyは低いですが、log_lossをみると減少しています。

これは、困りました。どちらのモデルがよいか判断しずらいです。

このようは場合には、バリデーションを変更するなどの方法がありますが、単純にどちらもファイルを提出してみて、良い方を採用するというアナログな方法もありです。

テストデータの予測とファイルの提出

せっかくなので、グリッドサーチで探索したベストパラメータの方からテストデータを予測します。

pred = best_model.predict(test_x) 

その予測結果を提出するために、sample_submissionを読み込みます。

submission = pd.read_csv('/content/drive/MyDrive/kaggle/Spaceship Titanic/sample_submission.csv')

sample_submissionをもとに、提出ファイルを作成します。

submission['Transported'] = pred
submission.to_csv('./Transported', index = False)

それでは、こちらを提出します。

submission.to_csv('best_sub_df',index=False)

ちなみに、グリッドサーチ前のXGBClassifierでは、以下のスコアでした。

グリッドサーチした方が、良かったです。

Kaggleで悩んだら

「Kaggle で勝つデータ分析の技術」

データ分析の最も有名なコンペティションプラットフォームであるKaggleにおけるテクニックや事例を、現時点で最新のものを整理した書籍。特徴量の作り方バリデーションパラメータチューニングなどについて、一般的な書籍ではあまり言及されないポイント等に解説。
>>【書評】Kaggleで勝つデータ分析の技術

以下の書籍は、Kaggleを始める方には本当にオススメの書籍です。Kaggleわからないこと悩んだことがあった方は、購入を検討してみください。

本だけでは物足りないという方は、動画のプラットフォームで学ぶこともオススメです。興味がございましたら、以下の無料オンライン説明会に参加してみてはいかがでしょうか。