こんにちは、ミナピピン(@python_mllover)です。今回は前回までに紹介した3つの機械学習アルゴリズムを使用してアンサンブル学習を実装していきたいと思います。
アンサンブル学習とは
アンサンブル学習のイメージとしてはいろんなアルゴリズムで分析してその結果をまとめて一番いいモデルを作るみたいなやつです。アンサンブルの手法で簡単なのは「Voting」という方法で結果をまとめる方法です。
「Voting」とは要は多数決のことで、ただの多数決のhard votingと、各分類器でクラスごとの予測確率を出し、それに基づいて決めるsoft votingという手法があります。
もう少し凝ったやり方としては、「stacking(スタッキング)」という方法があります。これは弱分類器の予測結果を新たな特徴量として、機械学習で結果を予測するという方法です。詳細についてはちょっと説明するのが大変なので、今回は「Voting」でアンサンブルしていきます。
Pythonでアンサンブル学習を実装してみる
というわけでここからは実際にPythonで実装していきましょう。
今回学習に使用するのは、皆さんおなじみのKaggleのタイタニックのデータです。以下のサイトから「titanic_train_mod.csv」と「titanic_test_mod.csv」をダウンロードしてください。
csvの中身は欠損値や特徴量を加工したタイタニックの乗客データです。特徴量エンジニアリングに関しては今回の話題ではないのでサクッと飛ばします。ダウンロードしたcsvは任意の場所に配置して、下記のpd.read_csvのパスを弄って読み込めるようにしておいてください。
#データの読み込み(パスは自分の環境に合わせて変えてください)
train = pd.read_csv('~/titanic_train_mod.csv.csv')
test = pd.read_csv('~/titanic_test_mod.csv.csv')
XGBboost
import pandas as pd
import numpy as np
import xgboost as xgb
from sklearn.model_selection import train_test_split
#データの読み込み(パスは自分の環境に合わせて変えてください)
train = pd.read_csv('titanic_train_mod.csv')
test = pd.read_csv('titanic_test_mod.csv')
#学習データを説明変数と目的変数に分ける
data = train[["Pclass", "Sex", "Age", "Fare"]].values
target = train['Survived'].values
# データを訓練データと正解データに7:3で分ける
X_train, X_test, y_train, y_test = train_test_split(data, target, test_size=0.3, shuffle=True)
dtrain = xgb.DMatrix(X_train, label=y_train)
dtest = xgb.DMatrix(X_test, label=y_test)
# パラメーター設定
params = {'max_depth': 4,
'eta': 0.3,
'objective': 'binary:logistic',
'silent':1,
'random_state':1234, # 学習用の指標 (RMSE)
'eval_metric': 'rmse'
}
#訓練データはdtrain、評価用のテストデータはdvalidと設定
watchlist = [(dtrain, 'train'), (dtest, 'eval')]
# モデル訓練
model = xgb.train(params,
dtrain,#訓練データ
early_stopping_rounds=20,
evals=watchlist
)
#予測
xgb_predict = model.predict(xgb.DMatrix(test[["Pclass", "Sex", "Age", "Fare"]].values), ntree_limit = model.best_ntree_limit)
# データを整形
xgb_predict = np.array([[1-i, i] for i in xgb_predict])
関連記事:【Python】元最強アルゴリズム「XGBoost」で機械学習をやってみた
XGBだけは他2つと予測結果の出力が若干異なり、Survivedが1である確率しか出力されません。
LightGBM
import lightgbm as lgb
# 訓練用
lgb_train = lgb.Dataset(X_train, y_train, free_raw_data=False)
# 検証用
lgb_eval = lgb.Dataset(X_test, y_test, reference=lgb_train, free_raw_data=False)
# パラメーター設定
light_params = {'task': 'train', # レーニング ⇔ 予測predict
'boosting_type': 'gbdt', # 勾配ブースティング
'objective': 'multiclass', # 目的関数:多値分類、マルチクラス分類
'metric': 'multi_logloss', # 検証用データセットで、分類モデルの性能を測る指標
'num_class': 2, # 目的変数のクラス数
'learning_rate': 0.1, # 学習率(初期値0.1)
'num_leaves': 23, # 決定木の複雑度を調整(初期値31)
'min_data_in_leaf': 1, # データの最小数(初期値20)
}
evaluation_results = {}
#学習
lgb_model = lgb.train(light_params, # 上記で設定したパラメータ
lgb_train, # 使用するデータセット
num_boost_round=200, # 学習の回数
valid_names=['train', 'valid'], # 学習経過で表示する名称
valid_sets=[lgb_train, lgb_eval], # モデルの検証に使用するデータセット
evals_result=evaluation_results, # 学習の経過を保存
early_stopping_rounds=20, # アーリーストッピングの回数
verbose_eval=0) # 学習の経過を表示する刻み(非表示)
# テストデータで予測
lgb_predict = lgb_model.predict(test[["Pclass", "Sex", "Age", "Fare"]].values, num_iteration=lgb_model.best_iteration)
参照記事:
Catboost
from catboost import CatBoost
from catboost import Pool
# 訓練用
CatBoost_train = Pool(X_train, label=y_train)
# 検証用
CatBoost_eval = Pool(X_test, label=y_test)
# パラメータを設定
params = { 'loss_function': 'MultiClass', # 多値分類問題
'num_boost_round': 1000, # 学習の回数
'early_stopping_rounds': 20 # アーリーストッピングの回数
}
# 学習
catb = CatBoost(params)
catb.fit(CatBoost_train, eval_set=[CatBoost_eval], verbose=False)
# テストデータで生存者予測
cat_predict = catb.predict(test[["Pclass", "Sex", "Age", "Fare"]], prediction_type='Probability')
参照記事:
3つのアルゴリズムをアンサンブルする
これら3つのアルゴリズムで予測した結果をアンサンブルしていきましょう。具体的にはテストデータを予測した数値の0、1の平均を求めます。
[0.2, 0.8](XGBの予測結果) + [0.5, 0.5] (LIGHTの予測結果) + [0.6, 0.4](CATの予測結果)
= [(0.2+0.5+0.6)/3 , (0.8+0.5+0.4)/3]
= [0.43, 0.56]
k1 = 1
k2 = 1
k3 = 1
voting_result = []
for i in range(len(test)):
voting = np.argmax(k1*xgb_predict[i] + k2*cat_predict[i] + k3*lgb_predict[i])
np.round(voting).astype(int)
voting_result.append(voting)
prediction_XG = np.round(voting_result).astype(int)
# PassengerIdを取得
PassengerId = np.array(test["PassengerId"]).astype(int)
# my_prediction(予測データ)とPassengerIdをデータフレームへ落とし込む
my_result = pd.DataFrame(prediction_XG, PassengerId, columns = ["Survived"])
# amsanble_resultとして書き出し
my_result.to_csv("amsanble_result.csv", index_label = ["PassengerId"])
そしてこれをhttps://www.kaggle.com/c/titanic/submitにアップロードしてmake submissionで採点してもらいます。結果は0.7700とXGboost Lightgbm Catboostとそれそれ単品でモデルを作成したときも精度は上がる傾向が見られました
終わり
これでアンサンブルの基本です。ここからが本番みたいなものですが、各モデルの重みをベイズで最適化することで、各モデルの比重を調整する作業が必要になります。これで精度が上がることが多いです。
参考記事:https://qiita.com/shinmura0/items/bcc8c4a06b9a49c943d6


コメント