Streamlit上でPyCaretを動かす方法

こんにちは。Qiita初投稿です。

# はじめに
PythonコードだけでWebアプリを作れる[Streamlit](https://streamlit.io)と
数行のコードで機械学習の前処理から推定までできる[PyCaret](https://pycaret.org)というものがあります。
Streamlit上でPyCaretを動かす方法を調べると、[ライブラリをイジる方法しかヒットせず](https://qiita.com/ryoshi81/items/e9560ade1f0adedbaf6c)、少しハードルが高かったのでライブラリをイジらずに動かす方法を試していこうと思います。


# 環境
```
Python 3.7
Streamlit 1.5.1
PyCaret 2.3.6
```

# 手順
クラス分類や回帰など問題ごとにライブラリが分かれているので、使用するものをimportします。
今回は回帰で試していきます。

```python
from pycaret.regression import *
```

StreamlitとDataFrameも扱うので、そちらもimportしておきます。

```python
import pandas as pd
import streamlit as st
```


## データの取得
今回はボストンの住宅価格データセットを使います。
※現在、ボストン住宅価格データセットは倫理的な問題が指摘されておりカリフォルニア住宅価格データセットなど他データセットの使用が推奨されています。（追記:2022/10/27）


```python
from pycaret.datasets import get_data
data = get_data("boston")
```


## 前処理
前処理は`setup関数`を使います。
デフォルトではデータの型推定が正しいか入力を求められますが、Streamlitでは入力を返せないので無効にします（html=False, silent=True）。

```python
pipe = setup(data, target="medv", html=False, silent=True)
```

## モデル比較
PyCaretでは学習に使うモデルを選択することができます。
それぞれのモデルの比較は`compare_models関数`で実行できます。
実行結果をpandasのDataFrameで取り出し、表示させます。

```python
best = compare_models() # モデル比較
best_model_results = pull() # 比較結果の取得
st.write(best_model_results) # 比較結果の表示
```


デフォルトでは決定係数R2のスコアが良い順にソートされて出力されます。
![スクリーンショット 2022-02-23 21.18.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/414198/2a9202fa-93a9-fc39-5c3c-8d9a108ab477.png)


## モデル作成
モデル作成は`create_model関数`を使用します。
モデル比較で表示されるモデル名（name）と、関数の引数で指定するモデル名（ID）が異なります。
（いつからからモデル比較結果のIndexにモデルIDが表示されるようになりました）

```python
model = create_model("et") # Extra Trees Regressorを使用
```

複数のモデルでブレンドモデルやアンサンブルモデルを作成することもできます。

```python:ブレンドモデル
et = create_model("et") # Extra Trees Regressorを使用
lightgbm = create_model("lightgbm") # Light Gradient Boosting Machine
model = blend_models(estimator_list=[et, lightgbm])
```

```python:アンサンブルモデル
ensembled_model = ensemble_model(model)
```

モデル作成は特にStreamlit向けに調整する事項はありません。


## モデルの可視化
モデルの可視化は`plot_model関数`を使用します。
可視化の内容は学習曲線や残差などいくつか用意されていますが、
リファレンスにもある通り、すべての可視化内容がStreamlitで表示できるようにはなっていません。
（対応していても表示に時間がかかるものもありました）
https://pycaret.readthedocs.io/en/latest/api/regression.html#pycaret.regression.plot_model

```python
plot_model(model, plot="cooks", display_format="streamlit")
```

クックの距離を描写するとこんな感じです。
![スクリーンショット 2022-02-23 21.19.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/414198/06657578-807b-e35f-d226-7f56f8b4570d.png)


## 予測
予測は`predict_model関数`を使います。
特にデータを指定しなければ、setup実行時にテスト用に分割してあったデータセットの一部で予測を行います。

```python
predictions = predict_model(model)
st.write(predictions)
```

予測結果はLabelというカラムに出力されます。
medv（住宅価格）を予測しましたが、何も考えずにモデルを作ったわりには、それなりの精度がでています。
![スクリーンショット 2022-02-24 8.33.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/414198/61040922-5826-e962-5697-3d7ec7bcbe99.png)


## st.cache
Streamlitの性質上、ユーザがUIを操作するたびにPyCaretの関数が再実行されることがあります。
@st.cacheを使って対策を取っておくと良いでしょう。

```python:create_modelの例
@st.cache(allow_output_mutation=True)
def create_model_cache(estimator):
    return create_model(estimator)
```


# さいごに
setupとplot_modelでそれぞれオプションを指定し、また必要に応じてst.cacheを活用すれば
Streamlit上でPyCaretを動かすことができます。
サンプルプログラムをGitHubに公開しているので、よければ試してみてください。

https://github.com/nockn/streamlit_example_pycaret


# 参考
- [PyCaret](https://pycaret.readthedocs.io/en/latest/index.html)
- [最速でPyCaretを使ってみた](https://qiita.com/s_fukuzawa/items/5dd40a008dac76595eea)
- [PyCaretとStreamlitでAutoMLのGUIツールをさくっと作ってみる](https://qiita.com/ryoshi81/items/e9560ade1f0adedbaf6c)
- [Pycaretを使って複数モデルをマージして予測してみました](https://qiita.com/ryosao/items/ee1aa64c972a6674f0af)