LoginSignup
10
7

More than 5 years have passed since last update.

partykitによる回帰木の可視化の調整

Last updated at Posted at 2017-09-18

はじめに

この記事では、Rで葉の多い回帰木を描画する際の工夫を記録しておきます。
使用するパッケージは決定木の計算でrpart、描画でpartykitを想定しています。

勉強のため、ご指摘等いただけると助かります。

(参考:partykitのドキュメント https://cran.r-project.org/web/packages/partykit/partykit.pdf)

動機

決定木で分析する際、木をある程度成長させたほうが良い示唆が得られることがあります。
過学習の問題とはうまく付き合う必要がありますが。

決定木の可視化を行うパッケージpartykitは、特に投入変数にカテゴリー変数が含まれる場合にとてもわかりやすいため、私はよく使っています。

ただ回帰木で葉が多いときの出力結果は、時折イマイチなことがあります。
探してもあまり良い記述がなかったため、ここに記録しておきます。

決定木の計算

ここではボストン市の住宅価格(Boston)を用います。
不動産価格を多くの投入変数から説明することを試みます。

データセットの中身は次のページがわかりやすく解説しています。
The Boston Housing Dataset

ライブラリ

library(MASS)
library(rpart)
library(partykit)

実行

>tree <- rpart(medv ~., data=Boston, method='anova')
>print(tree)


n= 506 

node), split, n, deviance, yval
      * denotes terminal node

 1) root 506 42716.3000 22.53281  
   2) rm< 6.941 430 17317.3200 19.93372  
     4) lstat>=14.4 175  3373.2510 14.95600  
       8) crim>=6.99237 74  1085.9050 11.97838 *
       9) crim< 6.99237 101  1150.5370 17.13762 *
     5) lstat< 14.4 255  6632.2170 23.34980  
      10) dis>=1.5511 248  3658.3930 22.93629  
        20) rm< 6.543 193  1589.8140 21.65648 *
        21) rm>=6.543 55   643.1691 27.42727 *
      11) dis< 1.5511 7  1429.0200 38.00000 *
   3) rm>=6.941 76  6059.4190 37.23816  
     6) rm< 7.437 46  1899.6120 32.11304  
      12) lstat>=9.65 7   432.9971 23.05714 *
      13) lstat< 9.65 39   789.5123 33.73846 *
     7) rm>=7.437 30  1098.8500 45.09667 *

決定木が得られました。

可視化

rpartでも可視化できますが、ここではpartykitを使用します。

> plot(as.party(tree))

図1.png

部屋数(rm)が多いほど価格が高いことがわかります。
この場合はbox chartでもわかりやすいです。

ただし実務上では、よりわかりやすく平均値を表示することがあります。
このためにplot関数にtype='simple'を渡します。

> plot(as.party(tree), type='simple')

図2.png

重なって見づらくなってしまいました。。
葉を少なくすれば重なりは解消されますがここでは木をある程度成長させる場合を考えます。

修正

さきほどの葉の重なりを解消するため、葉に記載する情報を整理することを考えます。
まず有効数字は幅を取りすぎているため、減らします。
また誤差の出力をやめることでも、スペースを確保できそうです。
無視して良いということではありませんが。

partykitのplotにおいて、tp_argsに値を渡すことで、ターミナルノードの出力を制御できます。
ここでは平均値とN数を、指定した桁数で、それぞれ y = , n = の形で返す関数を渡します。

plot(as.party(tree), type='simple',tp_args = list(FUN = function(info)
  c(paste('y = ',format(round(info$prediction, digits=1), nsmall = 1), sep=''),
    paste('n = ',format(round(info$n)), sep=''))
  ))

図3.png

重なりは解消されました。葉同士の平均値の上下関係も見やすいです。

おわりに

決定木はとても便利ですが、この便利さは結果の解釈の簡単さに起因しています。
よりわかりやすく可視化すれば、自分が見つけた示唆がより他人に伝わると考えています。

より良い方法がありましたら、ご教授いただけると幸いです。

10
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
7