Autogluonは大変優秀です


# これはなに？

<!-- 
近年、機械学習関連技術の進歩は目覚ましく、その中でもモデル作成・学習の自動化が進んでいる。

このことにより、機械学習に熟知していなくとも問題に機械学習を適応出来る一方、（モデルに対しても、実事象に対しても）本質的な意味・解釈がおざなりになりがちであると考察出来る。

それらを踏まえ、学習・チューニングにはあまり触れず、データ解釈・結果解釈に重きをおいたできるだけ**具体的**な**定式化**されたドキュメント作成を試みる（た。自己理解のためというのも大きい）


一般的な改善プロセスであるPDCAになぞらえて （こんなことを各予定）
 -->

近年、AutoMLと呼ばれる、機械学習の前処理からパラメータの探索やMLの評価まで自動でやってくれるフレームワークがある。

その中で、３行でAutoMLるれる、autogluonを使ってみたけど優秀過ぎてやることなかった…って話（ポエム）

# 要約

適当な使い方として、**AutoMLを回して、その結果ありきでデータを解釈し、次の試行へとつなげる**といったところ？

- 三行であと特にすることがない<!--　→　かなり高精度？-->
  - どのようなデータの何に着目して行くか？といった”**問**”の精度が求められる
- autogluonに**特徴量エンジニアリングのみ**させることはできる
  - 勝手に自然言語処理・ダミー変数化などもしてくれる
  - 特徴量エンジニアリングはほぼ不要
聞きかじりの付け焼刃でやっても大差なかった
- 精度を追求する　→　`presets`にクオリティーを指定する。
  - 最大クオリティだとCPU環境ryzen5 5xxx系で３０~４０分程度かかった。

ただ、**結果解釈のための特徴量分析**としては意味がるように感じる。
`name`の重要度が最大であったが、何故そうなるのか？といった考察の手段にはなる。
（しかしながら、内部で自然言語処理されているためよくわからない部分も多い）

また、内部処理によって、結構な多変量になっているので、注意が必要かもしれない。

なので、**問**の精度を上げるため、ガンガンに回して失敗できるのがautogluonの魅力と言えるかもしれない？

「未知の関係性をマシンパワーで探り当てていく」様な使い方が特徴をうまく使えるのではないか？と感じる。

最近、**マルチモーダルなMLもサポート**されたので、とりあえず作ってみて使ってみて、有用そうならさらに開発っていうのもよいかもしれない。

https://auto.gluon.ai/stable/tutorials/tabular/tabular-feature-engineering.html

とりあえず何かを論じ比較するにはtitanicではデータが少なすぎることに留意。
（つまるところ感想文）

## Do

https://auto.gluon.ai/stable/tutorials/tabular/tabular-quick-start.html

チュートリアルの三行コード

これだけで、前処理もされ、かなり高精度な分類が可能。

クオリティーを指定することができる。

Recommended Presets 
(For more details refer to https://auto.gluon.ai/stable/tutorials/tabular/tabular-essentials.html#presets):

|                          |                                                                        |
| ------------------------ | ---------------------------------------------------------------------- |
| presets='best_quality'   | Maximize accuracy. Default time_limit=3600.                            |
| presets='high_quality'   | Strong accuracy with fast inference speed. Default time_limit=3600.    |
| presets='good_quality'   | Good accuracy with very fast inference speed. Default time_limit=3600. |
| presets='medium_quality' | Fast training time, ideal for initial prototyping.                     |

~~~python
predictor = TabularPredictor(label=label).fit(train,presets='best_quality',time_limit=3600)
predictor.fit_summary(show_plot=1)
predictor.leaderboard(test)
~~~

### 全体

titanicデータセットopenmlからダウンロードしたモノからboatとbody列を除いたモノ25%をテストデータとして使用

~~~python

# 環境の構築
# jupyterにカーネルを追加して
# $ python3 -m venv autogluon
# $ source  autogluon/bin/activate
# $ pip install ipykernel
# $ python -m ipykernel install --name autogluon

# 依存関係のインストール（CPU）
# ! pip install -U pip
# ! pip install -U setuptools wheel
# #CPU version of pytorch has smaller footprint - see installation instructions in
# #pytorch documentation - https://pytorch.org/get-started/locally/
# ! pip install torch==2.0.1+cpu torchvision==0.15.2+cpu --index-url https://download.pytorch.org/whl/cpu
# ! pip install bokeh==2.0.1 #可視化のため
# ! pip install plotly nbformat>=4.2.0 
# ! pip install autogluon

# import 
import plotly.express as px
from bokeh.plotting import output_notebook
output_notebook()    # bokehでNotebook出力にはこの１行が必要

from sklearn.datasets import fetch_openml
from sklearn.model_selection import train_test_split

from autogluon.tabular import TabularPredictor
from autogluon.features.generators import AutoMLPipelineFeatureGenerator

# データのインポート
titanic = fetch_openml(data_id=40945, as_frame=True)
print(titanic['frame'].columns.values)
label='survived'
df=titanic['frame'].drop(['boat','body'],axis=1)
print(df.columns.values)
train ,test = train_test_split(df,test_size=0.25,random_state=False)
df

# 三行コード
predictor = TabularPredictor(label=label).fit(train)
predictor.fit_summary(show_plot=1)
predictor.leaderboard(test)

# 特徴量の重要度を結果のプロット
fi=predictor.feature_importance(train)
px.bar(fi.transpose().loc['importance']).show()
fi
~~~

## Check

autogluonが評価した特徴量の重要度を見てみる

~~~python
px.bar(fi.transpose().loc['importance']).show()
~~~

![newplot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3472791/c2a0b0ce-398c-cefa-7678-c0e62c9a90cf.png)
<!--
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3472791/1f27c413-d80d-1e06-7e4d-bee3e4bbe89e.png)
-->

高い順にname, sex, home.dest…と並んでいることが分かります。

データは下の様になっていて、nameには`Miss.`や`Mr.`の様な敬称が含まれる。

これらのが性別や社会的階級などを反映し、その結果が予測精度に関わっているのではないか〜（知れた話ですが…）

と逆向きの考察をすることができます。
（こういった方向で使うのがよさそうだなと思った）

~~~
pclass	survived	name	sex	age	sibsp	parch	ticket	fare	cabin	embarked	home.dest
0	1.0	1	Allen, Miss. Elisabeth Walton	female	29.0000	0.0	0.0	24160	211.3375	B5	S	St Louis, MO
1	1.0	1	Allison, Master. Hudson Trevor	male	0.9167	1.0	2.0	113781	151.5500	C22 C26	S	Montreal, PQ / Chesterville, ON
2	1.0	0	Allison, Miss. Helen Loraine	female	2.0000	1.0	2.0	113781	151.5500	C22 C26	S	Montreal, PQ / Chesterville, ON
3	1.0	0	Allison, Mr. Hudson Joshua Creighton	male	30.0000	1.0	2.0	113781	151.5500	C22 C26	S	Montreal, PQ / Chesterville, ON
4	1.0	0	Allison, Mrs. Hudson J C (Bessie Waldo Daniels)	female	25.0000	1.0	2.0	113781	151.5500	C22 C26	S	Montreal, PQ / Chesterville, ON
...	...	...	...	...	...	...	...	...	...	...	...	...
~~~

ということで分類する

~~~python
edf=df
l=[]
d={
    'officer':['Capt', 'Col', 'Major', 'Dr', 'Rev'],
    'royalty':['Don', 'Sir', 'the Countess', 'Dona', 'Lady'],
    'mrs':['Mme', 'Ms', 'Mrs'],
    'miss':['Mlle', 'Miss'],
    'mr':['Mr']
   }

for g in d:
    # for i in d[g]:
    #     edf[str('name_' + g )]=df['name'].str.contains(i)
    edf[str('name_' + g )]=df['name'].str.contains('|'.join(d[g]))
    l.append(str('name_' + g ))
l.append('survived')

px.bar(edf[l].corr()['survived'],title="生存者と敬称の相関").show()
edf[l].corr().loc['survived']
~~~

一定の相関が見て取れる（後付け解釈であることに留意）

![newplot(1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3472791/55770ee0-5c77-2e92-af53-8d95e8979de9.png)

<!--
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3472791/0018dbc3-ef10-2d84-a650-1fabc9a11b86.png)
-->
---
### 小ワザ

前処理だけしてもらう事が可能

~~~python
import seaborn as sns
auto_ml_pipeline_feature_generator2 = AutoMLPipelineFeatureGenerator()
efg=auto_ml_pipeline_feature_generator2.fit_transform(X=df)

sns.heatmap(efg.corr())
efg.corr()

px.bar(efg.corr()['survived']).show()
efg.corr()['survived']
~~~
![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3472791/5a1bf82e-21ed-3967-921e-aa56e28e0d1b.png)
<!--
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3472791/1c39bdb3-36ba-198d-2d96-c93aac729ecb.png)
-->
<!--
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3472791/c6db9093-658b-caec-8890-255379b31d50.png)
-->
![newplot(2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3472791/32a04ed7-008a-f545-4196-0fd04d6ad2e2.png)

---

デフォルトで勝手にsaveされていて、後でloadすることが出来る

~~~python
p2 = TabularPredictor.load(path="./AutogluonModels/ag-2023xxxx_xxxxxx")
p2.leaderboard(train)
~~~

https://auto.gluon.ai/stable/api/autogluon.tabular.TabularPredictor.load.html

https://auto.gluon.ai/stable/api/autogluon.tabular.TabularPredictor.save.html

# まとめ

精度が必要なときはpresetsだけ指定してガンガンにAutoML回し、異なる角度・情報から探っていくのがよさそう

聞きかじりの知識で試した結果を一例として

titanicデータセットopenmlからダウンロードしたモノからboatとbody列を除いたモノ25%をテストデータとして使用

「そもそも機械学習を正当に評価できるデータ量ではない」ということに留意


| モデル名                   | score test |                                                  |
| -------------------------- | ---------- | ------------------------------------------------ |
| XGBoost                    | 0.823171   | # デフォルト                                     |
| WeightedEnsemble_L2        | 0.844512   | # 特徴量エンジニアリング                         |
| NeuralNetTorch_r19_BAG_L1  | 0.859756   | # 特徴量エンジニアリング＋presets='best_quality' |
| NeuralNetTorch_r158_BAG_L1 | 0.853659   | # presets='best_quality'だけ                     |