JupyterNotebookを想定した機械学習の予測モデルの全体像（LightGBM + Optuna）

####目次
- はじめに
- モデル構築の目的
- データの前処理
- ダミー変数化
- 不均衡データの処理（アンダーサンプリング）
- 学習データとテストデータに分割
- LightGBMで学習モデルを作成
- 精度の検証
- ハイパーパラメータチューニング
- 学習モデル構築２
- 精度の検証２
- 最後に

#はじめに
Pythonや機械学習を学ぶ初級者の人にとっては初めて見るライブラリや、初めて使うメソッドが一度にたくさん出てくるので、コードの記述の目的を整理して振り返れる状態にしておくことはとても大事です。今回はLightGBMのハイパーパラメーターをoptunaでチューニングし、学習モデルを構築するステップについて振り返ります。

※以下のライブラリを使用しています。

```Python
import lightgbm as lgb
from sklearn.model_selection import train_test_split
from sklearn.model_selection import cross_val_score
import optuna
from sklearn.metrics import accuracy_score
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score
from sklearn.metrics import f1_score
from sklearn.metrics import roc_auc_score
from sklearn.metrics import roc_curve
```

※以下の環境で実行しています。
MacBook Air、Python3、JupyterNotebook



![LightGBM_logo_black_text.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1917703/41f40341-d8e2-8561-9c1b-b8c4938dbdeb.png)

![optuna-logo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1917703/1e9629ad-f726-7eac-84cc-d496f58ac07d.png)

# モデル構築の目的
A高校を受験する生徒の合否判定モデルを、過去の塾生のデータから構築する。

#データの前処理
####ダミー変数化
LightGBMの場合、学習モデルに投入するデータは数字が良いので、
塾生の模試の判定結果がA~Eだった場合に、このデータを数値化します。

####不均衡データの処理（アンダーサンプリング）
過去の合格者のデータが50で、不合格者のデータが500ある場合データの数に偏りがあるので、
不合格者のデータも50に揃えることで、データの偏りを無くします。
(今回はオーバーサンプリングはしない。)

####学習データとテストデータに分割
Train_test_splitで前処理したデータを、学習データとテストデータに分割します。

#LightGBMで学習モデルを作成
```Python
model = lgb.LGBMClassifier()
model.fit(X_train, y_train)
```
学習モデルを構築する方法は上記のコードで実現できます。
ただし今回はlgb.LGBMClassifier()のかっこの中に何も指定していないデフォルトのLightGBMです。パラメーターのセッティングについては下記のリンクを見ると良いでしょう。
https://lightgbm.readthedocs.io/en/latest/pythonapi/lightgbm.LGBMClassifier.html

#精度の検証
```Python
y_pred = model.predict(X_test)
y_proba = model.predict_proba(X_test)[:,1]
y_true = y_test['y'].values
y_pred = y_pred

print(accuracy_score(y_true, y_pred))
print(precision_score(y_true, y_pred))
print(recall_score(y_true, y_pred))
print(f1_score(y_true, y_pred))
# AUCの計算
print(roc_auc_score(y_true, y_pred))
print(roc_auc_score(y_true, y_proba))
```

学習モデルの精度を検証する方法は上記のコードで実現できます。

#ハイパーパラメータチューニング

```Python
def objective(trial):
    num_leaves = trial.suggest_int('num_leaves', 2, 5)
    max_depth = trial.suggest_int('max_depth', 3, 10)
    learning_rate = trial.suggest_uniform('learning_rate', 0.01, 0.05)
    n_estimators = trial.suggest_int('n_estimators', 50, 200)
    min_child_samples = trial.suggest_int('min_child_samples', 3, 5)
    
    params = {'objective': 'binary',
              'boosting_type': 'gbdt',
              'num_leaves': num_leaves,
             'max_depth': max_depth,
             'learning_rate': learning_rate,
             'n_estimators': n_estimators,
             'min_child_samples': min_child_samples,
             'random_state': 1}
    
    model = lgb.LGBMClassifier(**params)
    score = cross_val_score(model, X_train, y_train.values.ravel(), cv=5, scoring="roc_auc")
    roc_auc = score.mean()
    return roc_auc

study = optuna.create_study(direction='maximize')
study.optimize(objective, n_trials=30)

trial = study.best_trial
print('roc_auc: {}'.format(trial.value))
print("Best hyperparameters: {}".format(trial.params))
```

LightGBM + Optunaでハイパーパラメーターチューニングする方法は上記のコードで実現できます。

#学習モデル構築２

```python
params = {'objective': 'binary',
              'boosting_type': 'gbdt',
              'num_leaves': trial.params['num_leaves'],
             'max_depth': trial.params['max_depth'],
             'learning_rate': trial.params['learning_rate'],
             'n_estimators': trial.params['n_estimators'],
             'min_child_samples': trial.params['min_child_samples'],
             'random_state': 1}
    
model = lgb.LGBMClassifier(**params)
```

Optunaのベストパラメータによるモデルを構築する方法は上記のコードで実現できます。

#精度の検証２

```python
# モデルのインスタンスの作成
model.fit(X_train, y_train.values.ravel())

# ベストパラメータによるモデルの構築の精度確認
y_pred = model.predict(X_test)
y_proba = model.predict_proba(X_test)[:,1]
y_true = y_test['y'].values
y_pred = y_pred

print(accuracy_score(y_true, y_pred))
print(precision_score(y_true, y_pred))
print(recall_score(y_true, y_pred))
print(f1_score(y_true, y_pred))
# AUCの計算
print(roc_auc_score(y_true, y_pred))
print(roc_auc_score(y_true, y_proba))
```
ハイパーパラメータで学習後の精度を算出する方法は上記のコードで実現できます。

#最後に
https://lightgbm.readthedocs.io/en/latest/Parameters-Tuning.html
今回、ハイパーパラメータは、'num_leaves', 'max_depth', 'learning_rate', 'n_estimators', 'min_child_samples' を使用しましたが、上記のサイトによると精度を上げるには、以下を実行すると良いようです。
・'max_bin' を増やす（遅くなる可能性があります）
・'num_iterations'を増やし、'learning_rate' を減らす
・'num_leaves' を増やす（過剰適合を引き起こす可能性があります）
・トレーニングデータを増やす