LightgbmでkaggleのTitanicコンペに挑戦してみた

◯ バギングとは?
1. 訓練データからサンプルを弱学習器の数だけ取ってくる。
2. それぞれのサンプルデータを使って弱学習器を学習、予測する。
3. 予測結果をまとめて、最終的な出力結果を得る。

決定木とバギングを組み合わせた手法にランダムフォレストがある。
バリアンス(分散)を小さくすることが目的。

◯ ブースティングとは?
前の学習結果を次の学習に活かすようにする。
バイアス(誤差の平均)を小さくすることが目的。

ブースティングの代表的なアルゴリズム
・XGBoost
・Lightgbm

LightgbmでkaggleのTitanicコンペをやってみる。

# データの読み込み
import pandas as pd
import numpy as np

df_train = pd.read_csv('train.csv')
df_test = pd.read_csv('test.csv')​​
# 欠損値確認、データの可視化
import pandas_profiling as pdp
profile = pdp.ProfileReport(df_train)

# HTMLに出力
profile.to_file('train_data_profile.html')

Lightgbmで学習させるにあたり、欠損値の補完とカテゴリ変数の数値化が必要なのでその処理を行なっていく。

# 不要列を削除
from sklearn.preprocessing import LabelEncoder
df_train.drop(['PassengerId', 'Name', 'Cabin', 'Ticket'], axis=1, inplace=True)
df_test.drop(['PassengerId', 'Name', 'Cabin', 'Ticket'], axis=1, inplace=True)

# カテゴリ変数を数値に変換(ラベルエンコーディング)
le = LabelEncoder()

df_train['Sex'] = le.fit_transform(df_train['Sex'])
df_train['Embarked'] = le.fit_transform(df_train['Embarked'])

df_test['Sex'] = le.fit_transform(df_test['Sex'])
df_test['Embarked'] = le.fit_transform(df_test['Embarked'])

ホールドアウト法でデータの分割を行っていく。

# 説明変数と目的変数に分ける。
X_train = df_train.iloc[:, 1:]
y_train = df_train.iloc[:, 0]

# 訓練データ7割、検証データ3割に分ける
from sklearn.model_selection import train_test_split

X_train, X_valid, y_train, y_valid = train_test_split(
   X_train, y_train, test_size=0.2, random_state=1, stratify=y_train)
# LightGBMで学習、評価
import lightgbm as lgb

# 訓練データセットと検証データセットを作る
lgb_train = lgb.Dataset(X_train, y_train)
lgb_valid = lgb.Dataset(X_valid, y_valid, reference=lgb_train)

# パラメータを定義
lgb_params = {'objective': 'binary',  # 目的はbinary(二値分類)
             'max_depth': -1,  # 決定木の深さ(-1がデフォルト)
             'num_leaves': 31,  # 葉の数
             'metric': 'binary_logloss'}  # 評価指標

# 学習
results = {}
gbm_model = lgb.train(params=lgb_params,
                     train_set=lgb_train,
                     valid_sets=[lgb_train, lgb_valid],
                     early_stopping_rounds=20,
                     evals_result=results,
                     verbose_eval=2)

次に予測、検証、評価を行っていく。

# 予測値の出力
from sklearn.metrics import accuracy_score
y_preds = (gbm_model.predict(X_valid) > 0.5).astype(int)

print('score:', accuracy_score(y_valid, y_preds))

学習曲線を描き、過学習の有無を確認。

# 学習曲線の描画
import matplotlib.pyplot as plt

plt.plot(results['training']['binary_logloss'], label='train_loss')
plt.plot(results['valid_1']['binary_logloss'], label='valid_loss')
plt.xlabel('epochs')
plt.ylabel('log_loss')
plt.legend()
plt.show()
# 重要度の表示
importance = gbm_model.feature_importance()

pd.DataFrame({'features': X_train.columns,
             'importance': importance}).sort_values('importance', ascending=False)​

重要度の数字はその特徴量がどれだけ学習に使われたのかを示しており、特徴量の選択の際に役に立つ。相関係数と合わせて確認するとよい。

最後に提出用のフォーマットを作成していく。

# 予測値を計算
test_pred = (gbm_model.predict(X_test) > 0.5).astype(int)

# 提出ファイルの原型を作る
submit_file = pd.read_csv('./data/gender_submission.csv')

# submit_fileのSurvived列を予測値に変更
submit_file['Survived'] = test_pred

# submit_fileをcsv出力
submit_file.to_csv('LightGBM_submit.csv', index=False)

スコアは0.75程度だった。

今回lightgbmでTitanicコンペにチャレンジしたが、簡単な前処理だけである程度の精度のモデルを作ることができ、ベースラインのモデルを作る際に便利な手法だと感じた。この結果(重要度など)を用いて特徴量選択を行ったりハイパーパラメータのチューニング(グリッドサーチ、ベイズ最適化)を行っていけばさらに精度の良いモデルができそうなので、またチャレンジしてみたいと思う。