(備忘録-python)RandomforestをOptunaで調整する方法(分類)

IT系知識

よくoptunaをつかってRandomForestの調整をするのですが、コードをなくすことが多いため備忘録も兼ねて投稿します。コピペ用に作ったので、ぜひ試してみてください。

コードのみ

ライブラリのインポート

使うライブラリのインポートを行う。

import matplotlib.pyplot as plt
%matplotlib inline
import japanize_matplotlib
import pandas as pd

import seaborn as sns
import numpy as np

from sklearn.metrics import (
    confusion_matrix,
    accuracy_score,
    precision_score,
    recall_score,
    f1_score
)

import lightgbm as lgb
import optuna

from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import fbeta_score
from sklearn.model_selection import train_test_split

混合行列の可視化と特徴量重要度の可視化

def heat_map(cm):
    cm_matrix = pd.DataFrame(data=cm,columns=['Actual Positive:1','Actual Negative:0'],
                            index=['Predict Positive:1','Predict Negative:0'])
    
    # ヒートマップで描画
    plt.figure(figsize=(3, 3))
    heatmap = sns.heatmap(cm_matrix, annot=True, fmt='d',cmap='coolwarm')
    # heatmap.set_title('混同行列',fontsize=20)
    heatmap.set_xticks([0.5,1.5])
    heatmap.set_xlabel('予測',fontsize=15)
    heatmap.set_xticklabels(['Negative:0','Positive:1'],fontsize=12)
    heatmap.set_ylabel('真値',fontsize=15)
    heatmap.set_yticks([0.5,1.5])
    heatmap.set_yticklabels(['Negative:0','Positive:1'],fontsize=12)

def feature_importances_sort(fti):
    feat_df=pd.DataFrame()
    # print('Feature Importances:')
    for i, feat in enumerate(x_train.columns):
        # print('\t{0:20s} : {1:>.6f}'.format(feat, fti[i]))
        
        AAA=pd.DataFrame([fti[i]],index=[feat],columns=['importance'])
        feat_df=pd.concat([feat_df,AAA],axis=0)
    feat_df_sort=feat_df.sort_values(["importance"],ascending=False)
    return feat_df_sort

データのロード

以下のようにデータを準備する。

TRAIN_df=学習データ
VALID_df=検証データ

x_train=TRAIN_df[利用するカラム]
x_valid=VALID_df[利用するカラム]

target_columns=目的変数のカラム
y_train=TRAIN_df[target_columns]
y_valid=VALID_df[target_columns]

# train_test_split
X_tr, X_te, y_tr, y_te = train_test_split(x_train,y_train,random_state=42,stratify = y_train)

optunaの準備

def objective(trial):


    bootstrap = trial.suggest_categorical('bootstrap',[True,False])
    
    max_depth = trial.suggest_int('max_depth', 1, 100)
#     max_features = trial.suggest_categorical('max_features', ['sqrt','log2',"None"])
    max_features = trial.suggest_float('max_features', 0,1.0)
    max_leaf_nodes = trial.suggest_int('max_leaf_nodes', 1,1000)
    n_estimators =  trial.suggest_int('n_estimators', 1, 1000)
    min_samples_split = trial.suggest_int('min_samples_split',2,5)
    min_samples_leaf = trial.suggest_int('min_samples_leaf',1,10)
    
    
    model = RandomForestClassifier(bootstrap = bootstrap,
                                 max_depth = max_depth, 
                                 max_features = max_features,
                                 max_leaf_nodes = max_leaf_nodes,
                                 n_estimators = n_estimators,
                                 min_samples_split = min_samples_split,
                                 min_samples_leaf = min_samples_leaf,
                                 criterion="gini",random_state=0, n_jobs=-1)
    
    model.fit(X_tr , y_tr)
    # 推論
    y_pred = model.predict(X_te)

    # 評価
    #===========利用したい評価指標に変更===============
    score = fbeta_score(y_te, y_pred, average='binary', beta=0.5)

    return score

optunaの実行

study = optuna.create_study(direction='maximize',sampler=optuna.samplers.TPESampler(seed=42))
study.optimize(objective, n_trials=50)

print("=======ベストパラメータ========")
print(study.best_params)

調整したパラメータで学習

# チューニングしたハイパーパラメーターをフィット
optimised_RF = RandomForestClassifier(bootstrap = study.best_params['bootstrap'],
                                     max_depth = study.best_params['max_depth'],
                                     max_features = study.best_params['max_features'],
                                     max_leaf_nodes = study.best_params['max_leaf_nodes'],
                                     n_estimators = study.best_params['n_estimators'],
                                     min_samples_split = study.best_params['min_samples_split'],
                                     min_samples_leaf = study.best_params['min_samples_leaf'],                                     
                                     criterion="gini",random_state=0, n_jobs=-1)

optimised_RF.fit(x_train ,y_train)

評価

検証用データを用いて予測結果を出し、評価をする。混合行列と重要度も算出する。

y_pred_RF=optimised_RF.predict(x_valid)
valid_precision=precision_score(y_valid,y_pred_RF)
valid_recall=recall_score(y_valid,y_pred_RF)
valid_f1=f1_score(y_valid,y_pred_RF)

print(valid_precision,valid_recall,valid_f1)

混合行列の可視化。

cm = confusion_matrix(y_valid,y_pred_RF)
heat_map(cm)

特徴量重要度の可視化。

fti = optimised_rf.feature_importances_
feature_importances_sort(fti).style.bar(axis=0)

まとめ

完全に自分用の備忘録的にまとめたので詳細な説明は省いていますが、必要になったらぜひ使ってみてください。

コメント

タイトルとURLをコピーしました