low-code機械学習ライブラリ「PyCaret」でモデルを可視化してみた

# 概要
* low-codeで、機械学習ができるライブラリのPyCaretがついに、[v1.0](https://pypi.org/project/pycaret/#history)になりました。
* 機械学習モデルの **可視化** が便利なので、**モデルの可視化** に着目し、まとめてみます。
![evaluate_model.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/cd3e762c-869d-078d-03a1-093be387f370.gif)
* [ソース](https://github.com/pycaret/pycaret/blob/master/classification.py#L2700-L2840)を確認すると、部分的に内部で[Yellowbrick@HP](https://www.scikit-yb.org/en/latest/)（[Yellowbrick@qiita](https://qiita.com/tags/yellowbrick?page=1)）を利用しているようです。
* なお、Qiitaでも[PyCaretタグ](https://qiita.com/tags/pycaret)の下記で取り上げられています。
  * [最速でPyCaretを使ってみた](https://qiita.com/s_fukuzawa/items/5dd40a008dac76595eea)
  * [機械学習を自動化するライブラリ『PyCaret』入門](https://qiita.com/tani_AI_Academy/items/62151d7e151024733919)



# やること
列挙してみると下記の通りですが、pycaretの自動化により数行で実行できます。

* ①データ（クレジットカードのデフォルト）をロード
* ②前処理
* ③モデル比較（アルゴリズム間の性能比較）
* ④パラメータチューニング
* ⑤モデルの可視化（★ここがメインなので、冒頭でここを説明★）

# やってみる（⑤モデルの可視化）
* 手順上は **１番最後** なのですが、この記事の目的が**可視化なので、最初** に扱いたいと思います。

## ⑤モデルの可視化
* 出来上がったモデル（tuned_model)に対してモデルの特性を可視化していきます。
* evaluate_model関数に、出来上がったモデルを渡すことで、下記のメニューが表示されます。
* tuned_modelがどう出来上がったか？は後述します。まずは可視化を説明。

```python
evaluate_model(tuned_model)
```

* クリックするだけで、ROC曲線、学習曲線、混同行列等々、様々なプロットが可能です。
* 気になったものを取り上げて、一つ一つ見ていきたいと思います。
![evaluate_model.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/cd3e762c-869d-078d-03a1-093be387f370.gif)


### AUC (ROC曲線)
* AUCとは書いてありますが、ROC曲線を描画できます。
* 2クラス分類だったので、Positive/Negativeクラスに対して２種類描画されます。
![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/48278b08-9391-d565-5b0e-bec050fd5b72.png)

### Confusion Matrix
* こちらもよく見る混同行列です。ヒートマップで出力されます。
![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/35ca2830-4967-19db-8773-df6c353ef7ee.png)

* 二値分類だと見栄えが寂しいですが、多値分類になると色々な間違え方が見えてきます。
![mc_conf.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/1f18d43f-b670-1bcb-b03a-c0cab1c9ed36.png)

### Error
* 実際のクラス毎に、Positive/Negativeのどちらに予測をしたか？が表示されます。
![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/b78633b4-c798-a7ce-fb7d-1fb64a66d91e.png)

* こちらも多値分類だと、より有用性を感じることができます。
![mc_err.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/6fed06d5-e8f5-6d50-e828-8664c398841c.png)

### Dicision Boundary
* 決定境界です。**Creditデータセット** は、「デフォルトか、否か？」の不均衡データです。
* よって、Positiveクラスが **ごく少数** なので、境界が見えづらいですね。
![db.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/40fefc43-e6fa-681f-0b9d-8bdd20681953.png)

* 多値分類ですが、均衡性がある程度とれたデータセットでは、決定境界を確認できます。
* 以下は、lightGBMの決定境界なので、**Treeベースアルゴリズムのギザギザ** とした境界が確認できます。
![mc_db.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/c69d4fef-fda0-1392-04fa-e2bd722ef567.png)

* なお、こちらはおまけですが、決定境界を比較することでアルゴリズムの特徴を理解可能です。

|#|Logistic <br> Regression	|K Nearest <br> Neighbour|Gaussian <br> Process	|
|:---:|:---:|:---:|:---:|
|境界|![lr.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/36549124-ad5c-3b3f-4e92-ad0eef95fd0f.png)|![knn.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/8491ea91-0445-12c0-630d-265dac533e0c.png)|![GP.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/648469b7-4b85-01b2-a463-9fd933a5f4c2.png)|
|特徴|線形アルゴリズムの為 <br> 決定境界もまっすく|近傍点をグルーピング <br> するような境界| ベルカーブを意識させる <br> 滑らかな曲面 |

### Threshold
* しきい値毎の、precision/recall/f-measureが出力されます。
* 求められる予測特性に対して、しきい値をどの程度に設定すればいいかの検討に利用できます。
![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/0877d064-6394-6e50-759b-f658706abb3c.png)

### Precision Recall
* 同じく予測特性の議論に利用できるのが、Precision-Recallのグラフです。
* PrecisionとRecall共に、どの程度のしきい値であれば、予測特性を満たすか？の検討
に利用できます。
![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/c20d1c81-4623-8694-793f-05a6de0ed179.png)

### Learning Curve
* 学習曲線（学習の回数 vs 精度）が表示されます。
* TrainとCVセットに対してスコアが表示されるので、Underfittng/Overfittingの判断に利用できます。
* 学習曲線とunder/overfittingの判断については、[StanfordのAndrewNg先生の資料](http://cs229.stanford.edu/materials/ML-advice.pdf)が参考になります。
![income_lc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/43025277-9e84-7158-8814-b4ad8fa8dfe8.png)


### Validation Curve
* モデル毎の正則化パラメータに対する、Trainセット／CVセットのスコアが表示されます。
* LightGBMの場合は、max_depth(木の深さを制御する）パラメータを横軸に取ります。
* このモデルの場合、
    * max_depth=4のときに、汎化性能(CVスコア）が高い。
    * それ以上のときは汎化性能は上昇しない一方、Trainセットに対して（若干）過学習している。
    * よって、max_depthを制御したほうが良さそう。
* といった判断に利用できます。
![income_vc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/333d203b-4705-d992-ca83-dfe213398bad.png)

* 正則化を制御するパラメータはモデルにより異なるため、横軸はアルゴリズム毎に異なります。
* 例えばロジスティック回帰では、正則化のパラメータは **C** なので、横軸はCとなります。
![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/79c7c216-9bba-55d9-960e-935574a2e82e.png)

* 各アルゴリズムで、横軸になるパラメータを下記にまとめておきます。
* 詳細は、[ソースコードを参照](https://github.com/pycaret/pycaret/blob/master/classification.py#L2871-L2941)。なお、LDAは未サポートです。


|アルゴリズム|横軸|アルゴリズム|横軸|
|:---:|:---:|:---:|:---:|
|Decision Tree <br/> Random Forest <br/> Gradient Boosting <br/> Extra Trees Classifier <br/> Extreme Gradient Boosting <br/> Light Gradient Boosting  <br/> CatBoost Classifier | **max_depth** |Logistic Regression <br/> SVM (Linear) <br/> SVM (RBF)    | **C** |
|Multi Level Perceptron (MLP) <br/> Ridge Classifier | **alpha** |AdaBoost                 | **n_estimators** |
|K Nearest Neighbour（knn）| **n_neighbors** |Gaussian Process（GP）| **max_iter_predict** |
|Quadratic Disc. Analysis （QDA）| **reg_param** |Naives Bayes             | **var_smoothing** |


### Feature Importance
* このモデルがどの特徴量を重要視しているか？が表示できます。
![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/26f3b02a-9a99-ecda-0bc8-18a8daaaf6c3.png)


### Manifold Learning
* t-SNEを利用した多様体学習（次元圧縮）の結果を表示します。
* モデルというよりは、用いている特徴量、データ自体に分解能があるのか？
* 2値分類の場合、Positive/Negativeに分離可能なのかが確認できます。
* 今回のデータでは、前処理で24列->90列まで特徴量を増やしている（後述）なので、90列を次元圧縮により2次元にし、その結果を可視化しています。

![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/284a58f3-b572-f712-882c-56bc7c5e141f.png)


### Dimensions
* こちらも、データ自体の可視化で、[RadViz Visualizer]
(https://www.scikit-yb.org/en/latest/api/features/radviz.html)の結果を表示します。
![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/1d9ee299-17e2-2af1-5837-39c63a55add1.png)


# やってみる（①データロード～④チューニング）
### ①データロード
* pycaretには、様々なデータが搭載されています。詳細は、[Getting Data - PyCaret](https://pycaret.org/get-data/)を参照。
* 今回はクレジットカードのデフォルトを予測してみたいと思います。

```python
from pycaret.datasets import get_data
# creditデータセットをロードします。
# profileオプションをTrue指定すると、pandas-profilingによるEDAが走ります。
data = get_data('credit',profile=False)
```

### ②前処理
* creditデータセットは、２値分類（予測対象は、 **default**列）です。
* よって、分類のライブラリをインポートし、targetにdefaultを指定します。

```python
from pycaret.classification import *
exp1 = setup(data, target = 'default')
```

* 様々な前処理が自動で走ります。
* このデータセットの場合は、24列→90列まで特徴量が展開されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/e984831b-7cf0-353f-c63d-bf96111740aa.png)

### ③モデル比較
* 下記で、複数の分類アルゴリズムに対するモデリングが可能です。
* 求める予測の特性にもよりますが、まずは、AUCで並べておきます。

```python
compare_models(sort="AUC")
```

* GBM、XGB、CatBoost、LightGBM等が並びます
![evaluate_model_v2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/68d7b71d-dd3f-3963-a2e4-05b9ababd2bf.gif)



### ④パラメータチューニング
* AUCが一番良かったRandom Forestでも良いのですが、比較的計算の早いlightGBMで試してみます。

```python
tuned_model = tune_model(estimator='lightgbm')
``````
![tune_model_v1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/7f087f51-ab72-2a21-46c0-e8fef810ef12.gif)

* 指定できるアルゴリズムは下記の通りです。[docstring](https://github.com/pycaret/pycaret/blob/master/classification.py#L1558-L1584)でも確認できます。

|アルゴリズム|estimatorの指定|アルゴリズム|estimatorの指定|
|:---:|:---:|:---:|:---:|
|Logistic Regression      |**'lr'**         |Random Forest            |**'rf'**         |
|K Nearest Neighbour      |**'knn'**        |Quadratic Disc. Analysis |**'qda'**        |
|Naives Bayes             |**'nb'**         |AdaBoost                 |**'ada'**        |
|Decision Tree            |**'dt'**         |Gradient Boosting        |**'gbc'**        |
|SVM (Linear)             |**'svm'**        |Linear Disc. Analysis    |**'lda'**        |
|SVM (RBF)                |**'rbfsvm'**     |Extra Trees Classifier   |**'et'**         |
|Gaussian Process         |**'gpc'**        |Extreme Gradient Boosting|**'xgboost'**    |
|Multi Level Perceptron   |**'mlp'**        |Light Gradient Boosting  |**'lightgbm'**   |
|Ridge Classifier         |**'ridge'**      |CatBoost Classifier      |**'catboost'**   |



# まとめ
* モデルの可視化の方法をバラバラと書いてしまったので、最後に用途毎に整理して終えたいと思います。
* 入力データ→モデリング→結果を想定し、下記５用途でグルーピングしてみたいと思います。
    * A)　入力データや特徴量自体を理解する。
    * B)　モデルが見ている特徴量を理解する。
    * C)　モデルの学習状況（学習が足りない、過学習）を判断する。
    * D)　モデルの予測特性や、目的が達成できるしきい値を検討する。
    * E)　モデルの予測性能や予測結果を理解する。

|用途|観点|可視化手段|
|---|---|:---:|
|A)入力データや特徴量自体を理解する。|正／負のデータが分離可能か|**Manifold Learning** ![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/284a58f3-b572-f712-882c-56bc7c5e141f.png)|
||同上|**Dimensions** ![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/1d9ee299-17e2-2af1-5837-39c63a55add1.png)|
|B)モデルが見ている特徴量を理解する。|どの特徴量が重要か|**Feature Importance** ![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/26f3b02a-9a99-ecda-0bc8-18a8daaaf6c3.png)|
|C)モデルの学習状況（学習が足りない、過学習）を判断する。|予測性能向上を学習回数増で実現できるか|**Learning Curve** ![income_lc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/43025277-9e84-7158-8814-b4ad8fa8dfe8.png)|
||正則化により過学習をおさえられているか|**Validation Curve** ![income_vc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/333d203b-4705-d992-ca83-dfe213398bad.png)|
|D)モデルの予測特性や、目的が達成できるしきい値を検討する。|求める予測特性に対応するしきい値はどれか|**Threshold** ![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/0877d064-6394-6e50-759b-f658706abb3c.png)|
||PrecisionとRecallの関係性はどうか|**Precision Recall** ![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/c20d1c81-4623-8694-793f-05a6de0ed179.png)|
|E)モデルの予測性能や予測結果を理解する。|AUC（予測性能）はどの程度か。|**AUC** ![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/48278b08-9391-d565-5b0e-bec050fd5b72.png)|
||結果の境界線を理解する|**Decision Boundary** ![mc_db.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/c69d4fef-fda0-1392-04fa-e2bd722ef567.png)|
||予測の間違い方を理解する|**Confusion Matrix** ![mc_conf.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/1f18d43f-b670-1bcb-b03a-c0cab1c9ed36.png)|
||同上|**Error** ![mc_err.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/6fed06d5-e8f5-6d50-e828-8664c398841c.png)|

# 最後に
* 長文に、お付き合い頂きありがとうございました。
* よろしければ、**いいね、シェア**、してもらえると嬉しいです。
* ある程度、反響があったら、使いこなし編（パラメータ説明等）も書いてみようと思います。

# 関連記事
https://qiita.com/shnchr/items/c999e471ba940dacfe94

https://qiita.com/shnchr/items/7991f8ca7ae7acf1dad9

https://qiita.com/shnchr/items/be21f10748a14a2b3b40