11
8

More than 1 year has passed since last update.

Kaggle Titanicに初心者目線で挑戦してみた

Last updated at Posted at 2022-12-21

Kaggleとは

Kaggleは、データサイエンスや機械学習に特化したオンラインプラットフォームです。Kaggleでは、データセット、カーネル(Jupyter NotebookやPythonスクリプトなど)、およびモデルを公開して共有することができます。また、Kaggleには、多くのコンペティションも開催されており、参加者は、特定のタスクや問題に対して最も優れたモデルを提供することで、報酬や賞品を獲得することができます。

kaggleの初心者向けのチュートリアルとして用意されているTitanicを題材にします。

筆者の経験値と想定する読者

Kaggleのチュートリアル第6版を読み、今回、kaggleに初挑戦です。よって、これからkaggleに挑戦しようと思っている方の参考になればと思います。

今回すること

まず、ゴールは「Titanicコンペティションにsubmitする。」です。kaggleの雰囲気を味わいます!
そして、この記事ではそれまでに至った道筋を正直に語ります。
また、今回利用したものは下記になります。

  • LightGBM
  • Optuna
  • Xfeat

環境構築

kaggleに立ち向かう環境を整えました。

英語

日本語のコンペティションになかった言語の壁をkaggleでは感じます。それを取り払いました。翻訳できるものであれば何でも良いと思いますが、筆者はDeepLのChrome拡張機能を利用しました。
下図のような形で翻訳ツールが使用できるので便利だと思います。

image.png

今回は使いませんでしたが、Kaggle Notebook翻訳ヘルパーというKaggle Notebookを機械翻訳できるようにできる拡張機能もあり便利です。

コーディングの環境

筆者は使い慣れたGoogle colaboratoryを利用しました。
よって、kaggleからデータをダウンロードしてGoogle Driveに保存しました。
image.png

さてKaggleへ!

と、意気込んだのですが、一からフルスクラッチでコーディングするのは大変で手間がかかります。まずは下調べしました。

先人の知恵にあやかる

開催されているkaggleコンペティションにおいてもコードがいくつかの公開されており利用することが可能です。本来ならば、kaggleで公開されているコードをベースにするべきですが、初回ということで、日本語の解説記事を利用しました。
まずは、特徴量作成に

を利用しました。1
githubにコードがあるので実装する際の参考にしてください。

他人のコードを読むのは大変勉強になりました。
githubを利用し、特徴量を作成した後は下記のコードのように学習できるように準備しておきました。

train_set = dataset_dummies[dataset_dummies['Survived'].notnull()]
test_set = dataset_dummies[dataset_dummies['Survived'].isnull()]
del test_set["Survived"]

# trainデータを変数と正解に分離
X = train_set.values[:, 1:] # Pclass以降の変数
y = train_set.values[:, 0] # 正解データ

# 訓練データと検証データに分割
X_train, X_valid, y_train, y_valid = train_test_split(X, y, test_size=0.2, random_state=42,)

LightGBMでモデルを作成する

いろいろなコンペで活躍するLightGBMを使ってみました。
LightGBMについては下記の解説がわかりやすかったです。よってLightGBMの詳細についての記述は割愛します。

Titanicは二値分類なのでlightgbmで二値分類の一連の流れをしたメモを参考にLightGBMのモデルを作成します。

import lightgbm as lgb

train_data = lgb.Dataset(X_train, label=y_train)
eval_data = lgb.Dataset(X_valid, label=y_valid, reference= train_data)

# LightGBM のハイパーパラメータ
params = {
    # 二値分類問題
    'objective': 'binary',
    # AUC の最大化を目指す
    'metric': 'binary_logloss',
    # Fatal の場合出力
    'verbosity': -1,
}

# 上記のパラメータでモデルを学習する
model = lgb.train(params, train_data, valid_sets=eval_data,
                  verbose_eval=50,  # 50イテレーション毎に学習結果出力
                  num_boost_round=1000,  # 最大イテレーション回数指定
                  early_stopping_rounds=100
                 )


# テストデータを予測する
y_pred = model.predict(, num_iteration=model.best_iteration)

特徴量がしっかり考えられているおかげか、何もチューニングしていないLightGBMでもローカルの検証スコアは0.8156、kaggleのPublic Scoreはスコア0.7488がでました。

Optunaでパラメータを最適化する

 Optunaとは、株式会社Preferred Networksが公開しているハイパーパラメーター自動最適化フレームワークのことです。
Optunaについては下記が参考になりました。

def objective(trial):
    params = {
        'objective': 'binary',
        'metric': 'binary_logloss',
        'boosting': 'gbdt',
        'max_depth':trial.suggest_int('max_depth', 1, 10),
        'min_data_in_leaf':trial.suggest_int('min_data_in_leaf', 1, 80),
        'learning_rate':trial.suggest_loguniform('learning_rate', 0.001, 0.1),
        'lambda_l1': trial.suggest_loguniform('lambda_l1', 1e-8, 10.0),
        'lambda_l2': trial.suggest_loguniform('lambda_l2', 1e-8, 10.0),
        'num_leaves': trial.suggest_int('num_leaves', 2, 512),
        'feature_fraction': trial.suggest_uniform('feature_fraction', 0.4, 1.0),
        'bagging_fraction': trial.suggest_uniform('bagging_fraction', 0.4, 1.0),
        'bagging_freq': trial.suggest_int('bagging_freq', 0, 10),
        'min_child_samples': trial.suggest_int('min_child_samples', 5, 100),
        'verbosity': -1,
        'random_state': 0,
    }

   
    lgb_train = lgb.Dataset(X_train, y_train)
    lgb_valid = lgb.Dataset(X_valid, y_valid, reference=lgb_train)
    gbm = lgb.train(params, lgb_train, valid_sets=lgb_valid,
                    verbose_eval=False, num_boost_round=1000, early_stopping_rounds=100)

    

    y_prob = gbm.predict(X_valid)
    y_pred = np.round(y_prob)
    return accuracy_score(y_valid, y_pred)

#optunaで学習
study = optuna.create_study(direction="maximize",sampler=optuna.samplers.TPESampler(seed=42))
study.optimize(objective, n_trials=100)

optunaで見つけた最適なパラメーターstudy.best_paramsは以下のようになりました。

{'max_depth': 4,
 'min_data_in_leaf': 73,
 'learning_rate': 0.09090766031606874,
 'lambda_l1': 1.0538223942143251e-07,
 'lambda_l2': 0.001093200015848534,
 'num_leaves': 467,
 'feature_fraction': 0.4113382550460581,
 'bagging_fraction': 0.9146079596370836,
 'bagging_freq': 8,
 'min_child_samples': 92}

LightGBMのパラメータをOptunaで最適化したときの一番良かったスコアは0.8715でしたが、kaggleのPublic Scoreは0.79816でした。

カテゴリカルデータのエンコーディングの方法を変える

Target Encordingを使うことにしました。下記が参考になりました。Target Encordingの詳細は割愛します。

LightGBMのパラメータをOptunaで最適化したときの一番良かったスコアは0.8492でしたが、kaggleのPublic Scoreは0.78708でした。
今回はOne-Hot-Encordingのほうが有効ということでしょうか。

xfeatを使う

xfeatとは、株式会社Preferred Networksが公開している特徴量エンジニアリングと特徴量探索のためのライブラリです。
自動ですごい特徴量が作れるというコト!?

Target Encordingで変換したデータに対して用いました。

特徴量の作成

参考:特徴量エンジニアリングのライブラリ xfeat を使ってみて便利だったこと
性別ごとに、年齢、Pclass の平均、最大を集計した特徴量を作成するということをしました。

aggregated_df, aggregated_cols = aggregation(train_df,
                     group_key="Sex",
                     group_values=["Age", "Pclass"],
                     agg_methods=["mean", "max"],
                     )

xfeatのリポジトリ内のexamples/feature_selection_with_gbdt_and_optuna.pyを参考にしました。

  • ArithmeticCombinations
    ArithmeticCombinations を使うと、複数のカラムを四則演算するといった特徴量が計算できます。
def feature_engineering(df):
    cols = df.columns.tolist()
    encoder = Pipeline([
        #2つの数値データ
        ArithmeticCombinations(input_cols=cols,
                               drop_origin=False,
                               operator="+",
                               r=2,
                               output_suffix="_plus"),
        ArithmeticCombinations(input_cols=cols,
                               drop_origin=False,
                               operator="*",
                               r=2,
                               output_suffix="_mul"),
        ArithmeticCombinations(input_cols=cols,
                               drop_origin=False,
                               operator="-",
                               r=2,
                               output_suffix="_minus"),
        #3つの数値データの加算
        ArithmeticCombinations(input_cols=cols,
                               drop_origin=False,
                               operator="+",
                               r=3,
                               output_suffix="_plus"),
    ])
    return encoder.fit_transform(df)

特徴量を作成したことにより9個の特徴量が533個に増えました。

特徴量選択

参考:Python: xfeat を使った特徴量エンジニアリング

  • DuplicatedFeatureEliminator:重複した特徴量を削除できる
  • ConstantFeatureEliminator:定数になっている特徴量を削除できる
  • SpearmanCorrelationEliminator:高い相関を持った特徴量を削除できる
selector = Pipeline([
    xfeat.DuplicatedFeatureEliminator(),
    xfeat.ConstantFeatureEliminator(),
    xfeat.SpearmanCorrelationEliminator(threshold=0.8),
])

特徴量選択により20個に特徴量を減らすことができました。

LightGBMのパラメータをOptunaで最適化したときの一番良かったスコアは0.8492でしたが、kaggleのPublic Scoreは0.78708でした。自動で特徴量を作成して簡単に精度が上がるわけではなさそうですね。

結果

LightGBMで予測した結果を示します。One-Hotエンコーディング(25個)でLightGBM(Optunaでチューニング)が一番良いスコアでした。

特徴量 モデル kaggleのpublic Score
One-Hotエンコーディング(25個) LightGBM(チューニングなし) 0.7488
One-Hotエンコーディング(25個) LightGBM(Optunaでチューニング) 0.79816
Target Encording(9個) LightGBM(Optunaでチューニング) 0.78708
Target Encording(9個)に対してxfeatで特徴量作成、選択(20個) LightGBM(Optunaでチューニング) 0.78708

まとめ

参考となるコードの特徴量の利用、xfeatを用いて特徴量の作成、選択、optunaによるLightGBMのパラメータ最適化を行いKaggle Titanicにsubmmitしました。

今後の課題

  • データ分析から特徴量の作成までを自力で実装する練習をする
  • アンサンブルモデルを試す
  • コード、パラメータのの管理方法について調べて試す

感想 

他の人のコードを読むのは大変勉強になりました。過去に開催されたコンペティションだと、多くの解説記事があるので気軽に挑戦できるので、初心者にはおすすめだと感じました。もちろん、開催されているコンペティションに飛び込むことで得られることも多いと思うので、何か参加したいという意欲もわきました。
コンペをしていると、特徴量が増えてきて何がなんだかわからなくなります。さらに、パラメータやモデルなど様々な角度からのトライアンドエラーがあるので、今後はコード管理(実験管理?)の効率的な方法を考えたいと思います。

  1. 忠実に再現してもkaggleのスコアは0.78947にしなりませんでした。年齢予測に利用されているrandomforestregressorのseedが固定されていないからだと推測しています。seedの設定でかなりスコアが変化しました(何か情報があれば教えてください)

11
8
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
8