PyCaretにてモデルを較正(Calibration)する

## はじめに
* ２値分類等した際に、しきい値を決めPos/Negを分類するのは良いとして、、
* モデルの出力値を、Positiveとなる確率として見なしてよいか？は別問題となります。
* 上記を行いたい場合には、モデルによっては較正（Calibration）をする必要があります。
* この較正（Calibration）をPyCaretを使って行ってみたいと思います。

## モデルを作る
* PyCaretのチュートリアルに従い普通に決定木でモデリングしていきます。
* データセットとして、 diabetes（糖尿病）データセットを利用します。

### データのロード
```python
from pycaret.datasets import get_data
diabetes = get_data('diabetes')
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/ed5bc3cd-f234-fd15-18fc-476c5512a367.png)

### 決定木を使ってモデリング
* 分類をしたいので、pycaret.classificationをインポートします。
* そして、create_modelでdt(決定木)を指定すればモデリングできます。
* できたモデルはevalutate_modelで観察してみます。

```python
# 分類パッケージをインポート
from pycaret.classification import *
clf1 = setup(data = diabetes, target = 'Class variable')

# 決定木を作る
dt = create_model(estimator='dt')

# 可視化
evaluate_model(dt)
```

## 較正前のCalibration Curveを確認
* 下記ボタンで、Calibration Curveを確認できます。
  * 横軸は、モデルのスコアリング結果をビニングし、値順に並べたモノ
  * 縦軸は、そのビンまでに出現した、Positiveデータの割合
* 理想的な状況（※）では、
  * モデルの出力値に対してバランス良くPositiveデータが出現するので、
  * モデル（青線）が、斜めの理想線（破線）に近づきます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/f6a6db1d-e721-dde8-458c-9f12cb21e0e3.png)

## モデルを較正する(Calibration)
* Calibrationは、現状のモデルを上述（※）の状況に近づける作業です。
* ※の状況に近づけることにより、モデル出力値を、予測結果がPositiveである確率と見なしやすくなります。
* 実施方法は簡単で、calibrate_modelを使います。

```python
# calibrationする
calibrated_dt = calibrate_model(dt)

# 可視化する
evaluate_model(calibrated_dt)
```

* 先程に比べ、理想線（破線）にモデル（青線）が近づいた状況になりました。
* モデルのスコアリング結果に対して、
 * その時点でのPositiveの累積出現割合が線形増加する（※に近い状況）を作ることができました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/f838a268-ed25-6fcf-2fcf-e5ac6c0de3bb.png)

## 較正は何で実現されているか？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/f39d0c34-13f2-285a-804b-a5fcb0ec75b2.png)

* [sklearn.calibration.CalibratedClassifierCV](https://scikit-learn.org/stable/modules/generated/sklearn.calibration.CalibratedClassifierCV.html)を利用している様です。
* sklearnは較正の手法として'sigmoid'と'isotonic'に対応していますが、pycaretでも同様のドキュメンテーションとなっています。

## どのモデルが較正が必要"そうか？"
* SVMはマージン最大化の為、決定境界周辺を厳しく確認する関係でモデル出力値が0.5に集中し較正が必要。という点は[こちらの記事](https://yukoishizaki.hatenablog.com/entry/2020/05/24/145155#:~:text=SVM%E3%81%AF%E3%83%9E%E3%83%BC%E3%82%B8%E3%83%B3%E3%82%92%E6%9C%80%E5%A4%A7%E5%8C%96)で論じられていますが、他はどうでしょうか？
* どのモデルで較正が必要かの厳密な議論は、専門家にまかせて、本記事では、較正前後のCalibration Curveを書いてみてどういった傾向があるかを観察してみたいと思います。

* ロジスティック回帰
  * 元々、Positiveの確率として解釈可能なので較正前からバランス良いです。
  * 較正後もあまり変わらないですね。
* RBFカーネルSVM
  * 激しいですね。上記記事の通りマージン最大化で0.5付近にデータが寄る様です。
  * 較正してもあまり改善せず、モデル出力値を確率と見なし扱うのは危なそうです。
* ランダムフォレスト
  * 較正前から、ある程度バランスは良さそうです。
  * 今回は較正により、0.7あたりにピークが出てしまっています。
* XGBoost,LightGBM
  * 較正前でも、そこそこ。較正すれば少し落ち着く。

|アルゴリズム|較正前|較正後|
|:---:|:---:|:---:|
|Logistic <br> Regression|![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/777bad2b-babe-3ae6-d1f6-c46495c52a15.png)|![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/3c5606a1-0cc7-fb58-cff0-8fe53254cc28.png)|
|RBF SVM|![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/68a66eb9-7b0d-51b8-4e2c-ad8c56ecaac4.png)|![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/46e8c89e-7a28-8622-2e5b-672931096243.png)|
|Random  <br/>Forest|![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/95f443b4-a71b-3eae-2ee8-5aea5b54eef4.png)|![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/4cf7a2b2-561a-0ba1-5da1-1e9c694db15e.png)|
|XGBoost|![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/feb587ec-20b4-f7ff-bf60-ecdb1d5c2fd2.png)|![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/5aa89351-3667-9f30-6ec8-8d2a0461e11a.png)|
|LightGBM|![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/48e0cfaf-136b-5dc0-c80c-142cb0200a10.png)|![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/5037430a-f16d-17a6-ff1b-d7840405b63f.png)|

## 最後に
* PyCaretでモデルを較正してみました。
* モデル出力値をPositiveの確率と見なしたい時は、Calibration Curveの確認が必要ですね。
* 較正してもSVMのマージン最大化等、アルゴリズムが元々持つ特性で厳しいこともある。
* ロジスティック回帰のように、較正せずとも確率と見なしやすいモデルもあるので、用途によって使い分けるアプローチもあると思います。

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

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

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