XGBならいい結果出るかと思って色々試してみていました。
勾配ブースティング系は評判が良いと聞くね。
Kaggleのタイタニックの課題を、前回まではscikit-learnのMLPを利用してやっていましたが、XGBを利用してみることにしてみました。Otunaの使い方を覚えたので、ハイパーパラメータ調整をOptunaで行なって色々と試行錯誤してみました。
結果としては、初回試行が71%→76%まで改善という流れで、正直最初の課題スコアを越えることができませんでした^^;今回は、試行錯誤の過程を備忘録です。
前回の記事の続きです。前回の記事はこちらをご参考ください。
まずはデフォルトでXGB
Kaggle内のNotebookでも、以下のようにしてXGBoostを読み込むことができます。
XGBoostについては、こちらの記事もご参考ください。
from xgboost import XGBClassifier
cls = XGBClassifier().fit(X,y)
predictions = cls.predict(X_test)
単純にXGBoostに変更しただけだと、74%程度のスコアとなりました。
ハイパーパラメータチューニング
Optunaでの最適化を行う関数、「objective」の中に、XGBのパラメータを調べつつ追加してみました。
from xgboost import XGBClassifier
from sklearn.model_selection import cross_val_score
#1.目的関数の定義
def objective(trial):
learning_rate = trial.suggest_uniform('learning_rate', 0.01, 1)
max_depth = trial.suggest_int('max_depth', 2, 11)
n_estimators = trial.suggest_int('n_estimators', 50, 200)
min_child_weight = trial.suggest_int('min_child_weight', 1, 10)
gamma = trial.suggest_uniform('gamma', 0.01, 5)
subsample = trial.suggest_uniform('subsample', 0.01, 1)
clf1 = XGBClassifier(learning_rate=learning_rate,
max_depth=max_depth,
n_estimators=n_estimators,
min_child_weight=min_child_weight,
gamma=gamma)
score = cross_val_score(clf1, X, y, cv=3)
return np.mean(score)
#2.Optunaオブジェクトを作成
study = optuna.create_study(direction='maximize')
#3.Optunaでパラメータ探索
study.optimize(objective, n_trials=300)
#4.ベストパラメータ表示
study.best_params
XGBClassifierの「learning_rate」「max_depth」「n_estimators」「min_child_weight」「gamma」「subsample」というハイパーパラメータをプログラムのような値の範囲で何回も探索したりしてみました。
結局、一番スコアが高くなったのが、次のような設定でした。
from xgboost import XGBClassifier
cls = XGBClassifier(learning_rate=0.12699403654690683, max_depth=9, n_estimators=119, min_child_weight=6).fit(X,y)
predictions = cls.predict(X_test)
「learning_rate」「max_depth」「n_estimators」「min_child_weight」だけの最適化で行い、76%程度のスコアとなりました。
前処理の見直し
Nanデータを削っていたので、AgeとFareの欠損値の行を消すのではなく、テストデータと同じように平均値で埋めてみました。
train_data_3に入れる時、行を消す「.dropna」の処理を「.fillna」の処理へと変更しました。
#train_data_3 = train_data_2.dropna(axis=0)
train_data_3 = train_data_2.fillna({'Age':train_data_2['Age'].mean(), 'Fare':train_data_2['Fare'].mean()})
print(train_data_3.shape)
train_data_3.head()
この処理で、全体的に数パーセントスコアが底上げされたようになりましたので、この処理は結構有効だったように感じます。
ランキングは、スコア1とか出てるけど、どうやったらそんなになるんだろう。