Bokehで決定木の対話的可視化
scikit-learnの決定木をjupyter notebook上で対話的に可視化できるようにしてみた
背景
決定木の可視化
機械学習モデルを人が理解できるようにする技術に興味を持っています. 特に決定木は皆さん大好きな勾配ブースティング木 (GBM) の一要素でもあり, 決定木を人が理解できるように可視化することには価値があります.
機械学習モデルの中では決定木は人が理解しやすい(解釈可能性が高い)モデルと言われており, 例えばscikit-learnではgraphvizやmatplotlibで可視化することができます. www.haya-programming.com
ただしこの可視化は分岐条件がテキストで書かれていて直感的な理解がしにくく, 見た目もちょっとイケてないと感じます.
これに対してpythonではdtreevizという素晴らしい決定木可視化パッケージが公開されています. github.com www.st-hakky-blog.com
ちなみにdtreevizの作者による決定木の可視化に関する記事はめちゃくちゃ参考になります. explained.ai
ただしgraphviz周りの環境を構築しておく必要がありちょっと面倒です. また出力される図が静的なので,個々のデータサンプルに対して詳しく観察したい場合には不便に感じます.
平行座標プロット
ところで僕はデータ可視化にも興味をもっており, 例えば以下のwebサイトをニヤニヤと眺めるのが好きだったりします. www.data-to-viz.com
その中で平行座標プロット (parallel coordinates plot) というのがあり, データ次元が大きくなっても対応できる数少ない可視化方法として注目しています. www.data-to-viz.com en.wikipedia.org
話を決定木の可視化に戻すと, 決定木における条件分岐は平行座標プロットの座標を分割することに対応しています. 平行座標プロットっぽく決定木を可視化してあげると面白いのでは? と思ったのが今回記事を書くきっかけです.
決定木と平行座標プロットの組合せは既に誰かやってそうだと思ったのですが, ググっても意外と見当たらなかったので自分でやってみました.
iparacoord
対話的に平行座標プロットするためのpythonモジュール iparacoord (interactive parallel coordinates) を作りました.
動作環境
python3.7での動作を確認しています. Anacondaで環境構築した場合に含まれる以下のパッケージにのみ依存しています.
- numpy 1.16+
- pandas 0.24+
- scikit-learn 0.21+
- matplotlib 3.1+
- bokeh 1.2+
- jupyter notebook 6.0+
使い方
jupyter notebookでの使い方を説明します.
まずはモジュールをインポートします.
import iparacoord from sklearn import datasets, tree
scikit-learnのワインのデータセットで決定木を学習して可視化します.
# ワインのデータセットで決定木を学習 wine = datasets.load_wine() X, y = wine.data, wine.target estimator = tree.DecisionTreeClassifier(max_depth=3).fit(X, y) # 学習した決定木を可視化 pct = iparacoord.ParallelCoordinatesTree(estimator) pct.visualize(X, y, feature_names=wine.feature_names, target_names=wine.target_names)
決定木の分岐条件に対応する特徴量の名称と閾値の数値が表示されます. 色付きの折れ線が決定木の判断経路 (decision path) を表しており, 上から順に条件分岐していく流れが読み取れます. データの数だけ判断経路があり,気になるものがあればマウスオーバーすると強調されます. クリックするとマウスを離しても強調されたままにできます.
マウスをスクロールするとズームイン・ズームアウトできます. 決定木の深い階層で表示が小さかったり重なったりして見えない場合に使えます.
決定木全体のふるまいを可視化する大域的な説明 (global explanation) に加えて 個々のデータサンプルに対する予測を可視化する局所的な説明 (local explanation) を与える機能もあります. 図を可視化した状態でデータサンプルをpredictメソッドに与えます.
pct.predict(X[0])
与えたデータサンプルに対する予測の判断経路が図に追加されます (ただし図が更新されるのに結構時間がかかります…).
クラス識別 (classification) だけでなく回帰 (regression) にも対応しています.
# ボストンのデータセットで決定木を学習 boston = datasets.load_boston() X, y = boston.data, boston.target estimator = tree.DecisionTreeRegressor(max_depth=2).fit(X, y) # 学習した決定木を可視化 pct = iparacoord.ParallelCoordinatesTree(estimator) pct.visualize(X, y, feature_names=boston.feature_names, target_names=['MEDV'])
応答変数の真値の大小で判断経路の色にグラデーションをかけています.
まとめ
今までにない面白い決定木の可視化ができたと思うので満足です. よりよい可視化方法や追加で欲しい機能などコメントいただけると喜びます.
もっとBokeh力を高めて色々作っていきたい….