[Python]Graphviz不要の決定木可視化ライブラリdtreepltをつくった

# 概要
この記事では、私がつくったライブラリ`dtreeplt`について解説します。
決定木可視化界隈に革命を起こすことが目的です。

![result.png](https://qiita-image-store.s3.amazonaws.com/0/203205/6659da4c-025f-3891-3ffd-c84e5312374a.png)
↑こんなのをmatplotlibとnumpyのみで描画します。すごいぞ。

# 追記（2020/01/05）
dtreepltを公開したすぐ後に出たsklearn0.21にて、 `sklearn.tree.plot_tree` が実装されてました。。
dtreepltと同様に、Graphvizを使わずにmatplotlibで決定木を描画できるようになりました。
dtreepltに独自性がないわけではないのですが、サクッと決定木みたいなーってときにはplot_treeを使ったほうが楽でしょう。
サンプルコードと出力結果は下記のとおりです。（githubのREADMEにも載せてます）

```python
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
import matplotlib.pyplot as plt
from sklearn.tree import plot_tree
%matplotlib inline

iris = load_iris()
model = DecisionTreeClassifier()
model.fit(iris.data, iris.target)

fig = plt.figure(figsize=(15, 8))
ax = fig.add_subplot()
plot_tree(model, feature_names=iris.feature_names, ax=ax, class_names=iris.target_names, filled=True);
```
![plot_tree.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203205/674c9c35-e81f-e395-9238-ae64f06e9297.png)


# 決定木可視化における課題
データ分析各位、決定木は好きですか？わたしは好きです。
データ分析初学者のファーストステップとして、IrisとかTitanicをscikit-learnのDecisionTreeClassifierで分類してexport_graphvizで可視化することが多いですよね。
初学者に限らず決定木による可視化は解釈性が高く、よく使われることと思います。
ただ、可視化の際に使われるGraphviz、インストールがめちゃめちゃ難易度高いことに定評があります。
Windows, Mac, Linuxで変わってくるのも辛いポイントですね。
「データ分析やるぞ！」と意気込みAnacondaを入れたPython初心者が、Graphvizのインストールで躓いてしまうのは悲しいです。
そこで、Graphvizを使わずにnumpyとmatplotlib（と、もちろんscikit-learn）のみで決定木を可視化するライブラリ`dtreeplt`をつくりました。
[Githubリポジトリはこちら](https://github.com/nekoumei/dtreeplt)
# インストール
~~これだけです。最新のAnaconda環境ならなんの問題もないと思います。~~

```bash
pip install dtreeplt
```
-----------------------------
※2019/06/16追記
ノードが重なって表示される致命的なバグを修正したので、gitから最新版をinstallするのが一番確実です。

```bash
pip install git+https://github.com/nekoumei/dtreeplt.git
```
upgradeの場合は下記のようにしてください

```bash
pip install git+https://github.com/nekoumei/dtreeplt.git -U
```
PyPIも一応更新済なんですが、今後もgitが常に最新となるのでこちらを推奨します

---

numpy, matplotlib, scikit-learnが入っていない場合は、事前に↓みたいにして入れてください。

```bash
pip install numpy matplotlib scikit-learn
```
また、これらのバージョンが古くてうまくいかない場合は↓みたいにupgradeしてください。

```bash
# numpyのバージョンが古かった場合
pip install numpy --upgrade
```
Pythonのバージョンは`3.6.X`以上を想定しています。
以上で準備は終わりです。
# Quick Start
Jupyter Notebookで、3行で確認できます。
![スクリーンショット 2019-02-17 15.35.33.png](https://qiita-image-store.s3.amazonaws.com/0/203205/8f6f7458-2fe7-8adb-5069-d5270274660d.png)
本当は、`dtreeplt`インスタンス作成時にパラメータで学習済決定木モデルを渡す必要がありますが、モデルが渡されなかった場合、自動的にIrisデータセットからモデルを作成して可視化します。
# ほんとうのつかいかた
このライブラリは、アヤメの分類器可視化専用ではないので任意の決定木モデルを渡して可視化することができます。下記のとおりパラメータを渡してあげてください。
(結局アヤメの分類をしている)

```Python
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from dtreeplt import dtreeplt

iris = load_iris()
model = DecisionTreeClassifier()
model.fit(iris.data, iris.target)

dtree = dtreeplt(
    model=model,
    feature_names=iris.feature_names,
    target_names=iris.target_names
)
fig = dtree.view()
#if you want save figure, use savefig method in returned figure object.
#fig.savefig('output.png')
```
dtree.view()はmatplotlibのfigureオブジェクトをreturnするので、savefigしたいときはそれを使えばOKです。
また、fontはmatplotlibのデフォルトに依存するので日本語が出ない！とかがあったら `matplotlib 日本語`とかでググれば解決すると思います。

# Future Works
そもそも、Graphvizを使わずに可視化したい！と思ったきっかけが[dtreeviz](https://github.com/parrt/dtreeviz)というライブラリを使おうとしたときでした。
dtreevizは決定木可視化をめっちゃ良いかんじにしてくれるライブラリです。語彙力がないですね。
[このissue](https://github.com/parrt/dtreeviz/issues/33)と似たようなエラーを踏んでしまって、自分のMac環境では未だ使えていません。（Linux環境では使えました）
そこで、dtreevizをGraphvizなしでやりたい！という思いからdtreepltをつくりはじめました。
なので、いずれはdtreevizをmatplotlibで表現することが目標です。のんびり作っていくので気長にお待ちください。

# 余談
## その1
dtreepltのキモは、決定木の情報をいかにして取ってくるかです。実は決定木オブジェクトにはすべての情報が入っているので、それをとってくるだけです。
このあたりの知見は1年くらいまえにやった[3-Dインタラクティブ決定木](https://qiita.com/nekoumei/items/77d062d085c09e4a2c6a)のときに雑ですが解説しています。
興味があるひとはそちらもご覧いただければ。

## その2
個人的には、Graphviz自体は大好きです。パス分析も容易にできるので素晴らしいツールだと思います。
ただ、決定木を可視化するためだけにPython外のツールを導入するのはちょっとめんどくさいんですよね。
決定木のように構造が単純であればmatplotlibだけでもじゅうぶん描画できます。