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をチームごとまとめて新しく特徴量にする
などなど…