目指せ"Another" バトル優勝!
columbia2131
初投稿なので不備等あると思いますが、ご了承ください。今回のデータにおいてカテゴリ変数が多く、エンコーディングで悩んでいる方が多いと思います。そこでカテゴリ変数をそのまま扱える決定木ベースの勾配ブースティング手法である「CatBoost」を用いた簡単なベースラインを実装します。工夫すれば外部データを用いずともPublicLBが0.55を超えると思います。またアンサンブル学習のモデルの1つとして参考になれば幸いです。
まず「CatBoost」をインストールします。
!pip install catboost
また前提としてディレクトリ構造は以下の通りです。参考にしてください。
├── input│ ├── train_data.csv│ └── test_data.csv├── notebooks│ └── catboost_baseline.ipynb└── output
以下、実装コードです。
# パッケージのimport import numpy as np import pandas as pd from sklearn.model_selection import KFold from catboost import Pool, CatBoostClassifier from sklearn.metrics import accuracy_score
INPUT_TRAIN = './input/train_data.csv' INPUT_TEST = './input/test_data.csv' N_SPLITS = 5 SEED = 0 LIST_PLAYER = ['A1', 'A2', 'A3', 'A4', 'B1', 'B2', 'B3', 'B4']
# データの読み込み train = pd.read_csv(INPUT_TRAIN) test = pd.read_csv(INPUT_TEST)
# 前処理 def processing(df: pd.DataFrame): """ 欠損値処理: weapon:str型'NaN'埋め level :0埋め rank :str型'NaN'埋め """ for player in LIST_PLAYER: df[f'{player}-rank'].fillna('NaN', inplace=True) df[f'{player}-level'].fillna(0, inplace=True) df[f'{player}-weapon'].fillna('NaN', inplace=True) """使わない列の除去""" drop_columns = ['id', 'period', 'game-ver', 'lobby'] df.drop(columns=drop_columns, axis=1, inplace=True) return df train = processing(train) test = processing(test)
# 説明変数と目的変数を分ける train_X = train.drop('y', axis=1) train_y = train.loc[train_X.index, 'y'] # objectの列番号を取得 categorical_features_indices = np.where(train_X.dtypes==np.object)[0]
# Catboostによる予測 scores = [] y_pred = [] kf = KFold(n_splits=N_SPLITS, shuffle=True, random_state=SEED) for i, (tr_idx, va_idx) in enumerate(kf.split(train_X)): tra_X, val_X = train_X.iloc[tr_idx], train_X.iloc[va_idx] tra_y, val_y = train_y.iloc[tr_idx], train_y.iloc[va_idx] train_data = Pool(tra_X, tra_y, cat_features=categorical_features_indices) valid_data = Pool(val_X, val_y, cat_features=categorical_features_indices) model = CatBoostClassifier(eval_metric='Logloss', num_boost_round=10000, random_seed=SEED) model.fit(train_data, eval_set=valid_data, early_stopping_rounds=10, verbose=False, use_best_model=True) tmp_pred = model.predict(val_X) tmp_cv = accuracy_score(tmp_pred, val_y) scores.append(tmp_cv) y_pred.append(model.predict(test)) print(f'epoch {i+1}/{N_SPLITS}: {tmp_cv}') cv = sum(scores)/len(scores) print(f'CV:{cv}')
epochs 1/5: 0.5469187145557656 epochs 2/5: 0.5436672967863894 epochs 3/5: 0.5463894139886578 epochs 4/5: 0.5485822306238185 epochs 5/5: 0.5434404536862004 CV:0.5457996219281663
# submit.csvの作成 sub = pd.DataFrame(index=test.index+1, columns=['y']) sub.index.name = 'id' # 多数決を取る(今回fold数が5より合計して3以上なら1、3未満なら0) sub['y'] = np.where(sum(y_pred)>=3, 1, 0) sub.to_csv(f'./output/cv{cv}.csv')
# PublicLB: 0.5472
以上で実装は完了です。確率で出力することも可能です。詳しくは公式のドキュメント等を確認してください。(参考:[CatBoost-Python package training parameters](https://catboost.ai/docs/concepts/python-reference_parameters-list.html))
この実装をもとにスコアを向上させる方法は様々あります。その例として・トピックに挙がっている外部データを用いる・他のモデルとアンサンブル学習をする・levelやrankをチームごとまとめて新しく特徴量にするなどなど…