決定木系モデルを一通り学ぶ。
決定木は、予測値の解釈性に優れている点で魅力的なモデルである。一連の質問に基づいて決断を下すという方法を繰り返すことでデータを分類する。
Classificationには分類木、Regressionには回帰木が対応する。
質問によるデータの分割は、情報利得(information gain: 分割された集合の要素のばらつきの減少)が最大となる特徴量で分割する方法をとる。情報利得は以下のように定式化される。
は分割を行う特徴量、は親(分割前)のデータセット、はj番目の子ノード(分割後)のデータセット、は不純度(impurity: 異なるクラスのサンプルがノードにどの程度でまざっているか定量化する指標)、は親ノードのサンプル数、はj番目の子ノードのサンプル数をそれぞれ指す。式の通り、は子ノードの不純度が低いほど大きくなる。**不純度指標をエントロピーとして、親ノードから3つ以上の子ノードを生み出すことを繰り返すアルゴリズムは"C4.5"と呼ばれることで有名である。**上式はm個の子ノードに分割する一般的な式だが、組み合わせ探索空間を減らすため、ほとんどのライブラリは二分決定木を実装している。つまり、親ノードから、子ノード・に分割される。よって式は以下のようになる。
親ノードから左右2つの子ノードを生み出すことを繰り返すアルゴリズムは"CART"(Classfication And Regression Tree)と呼ばれることで有名である。
CARTでは分類タスクの時、twoing crietionという情報利得について別のメソッドをオプションに持っていて、
で規定される。
note: あらゆるライブラリで実装されているfeature_importance、つまり、特徴量の重要度は何を示しているのかというと、特徴量で分割することでどのくらい情報利得が生じたかを表している。
不純度(impurity)を表す指標は分類木では、ジニ不純度(Gini impurity):、、エントロピー(entropy):、分類誤差(classification error):の3つ、回帰木では平均2乗和誤差(MSE)が存在する。
誤分類の確率を最小化する条件と解釈できる指標である。定義は以下。
最大になるのはクラスが完全に混合されている時である。
すべての空でないクラスを対象にしたエントロピーの定義は以下のようになる。
はノードにおいてラベルがクラスのサンプルの割合を指す。エントロピーは平均情報量ともいわれる。
「情報量(じょうほうりょう)やエントロピー(英: entropy)は、情報理論の概念で、あるできごと(事象)が起きた際、それがどれほど起こりにくいかを表す尺度である。ありふれたできごと(たとえば「風の音」)が起こったことを知ってもそれはたいした「情報」にはならないが、逆に珍しいできごと(たとえば「曲の演奏」)が起これば、それはより多くの「情報」を含んでいると考えられる。情報量はそのできごとが本質的にどの程度の情報を持つかの尺度であるとみなすこともできる。」(by wiki)
ここで、 事象が起こる確率をとするとき、 事象 が起こったことを知らされたとき受け取る(選択)情報量 を
と定義される。よってエントロピーは有限集合中、起きうる全事象から受け取る情報量をそれぞれの事象が起きる確率で重みづけ平均した情報量であり、平均情報量と呼ばれる所以である。
よって今回は有限集合であるノードから受け取ることのできる平均情報量を表しているのである。
2値分類の場合、でエントロピーは最小になる。エントロピーが最大になるのはジニ不純度と同様にクラスが完全に混合されている場合、つまりの時である。
以下のように定義される。
多数派がどれだけ大多数か示すことで純度を測っている。
以上3つの指標を比較してみよう。
ここでは2値分類を例として考える。クラス(0, 1)に対して親ノードのサンプル数を(40, 40)とする。以下の2通りの分岐を考えてみる。
それぞれのケースで情報利得はどのような値をとるのだろうか?
ジニ不純度の場合、
A: 0.125, B: 0.16666666666666669
となり、Bでの分割を優先することがわかる。実際問題そちらの方がより純粋である。
エントロピーの場合、
A: 0.1887218755408671, B: 0.31127812445913283
となり、同様にBでの分割を優先することがわかる。このように、ジニ不純度とエントロピーは非常によく似た結果になることが知られていて、2択に時間をかける優先性はあまりない。
分類誤差の場合、
A: 0.25, B: 0.25
となり、AとBを同等に評価していることがわかる。このように分類誤差はノードのクラス確率変化にあまり敏感ではないので決定木の成長に適していない。一方、過学習を防ぐため、決定木の分岐の深さに制限を設ける剪定(prune)には役立つ。
ちなみにtwoingはどうなるのか、
A: 0.25, B: 0.33333333333333337
なるほど、一応Bをうまいこと優先しているようだ。
回帰に決定木を使用するには、連続値変数に適した不純度指標が必要である。そこで、ノードの不純度指標として代わりにこの指標が使われ、
と定義される。ここで、はノードのサンプル数、はノードのサブセットインデックスの集合、はラベル(真の目的値)、はサンプルの平均(予測された目的値)として扱う。
決定木回帰の文脈で、この指標はよく「分割後のノード分散」と呼ばれる。分割条件はこれにならってよく「分散減少」(variance reduction)と呼ばれる。
それでは単純な1本だけの決定木を実装してみよう。ここでは単純のため分類木に焦点をあてて実装してみる。(前に作った関数を流用したいのでクラス内メソッドに書き直しません、後決定木の図示はめんどいのでSklearnに任せます..)
親ノードから左右ノードへ分岐する際に情報利得が最も大きくなるように、分岐の基準とする特徴量とその閾値を求める。
今回はSklearnのIrisデータをお試しに使う。まずはデータを読み込む。
先ほどの関数を使ってみると、
Information gain: 0.3294995369039634, Best threshold: 3.0, Best feature: petal length (cm)
petal length (cm) 特徴量で閾値を3にした時に初めのベストな分割が行えるようだ。
ノードクラスをつくって、クラス内でsplitメソッドにより子ノードを再帰的に繰り返す。これは左右分割後に、それぞれに対応するノードクラスをleftとright変数に格納してあげることで達成できる。
具体的に、変数left.method_name
はleftに格納されたノードクラスのmethod_name
を呼び出していて、そのメソッドでさらにleftノードクラスのleftとrightに分割されたノードクラスが格納され、さらに格納されたノードクラスのmethod_name
が呼び出されるというように繰り返される。制限をつけないと無限ループするので、ストップする基準としてmax_depthに達するか、左右子ノードの不純度が0(クラスが1種類しか含まない)という条件を使うことにする。
結果として学習後にこのノードクラスが成長後のすべてのノードを蓄えていることになる。また、IG_maxを特徴量ごとに足し合わせれば各特徴量の重要度を計算できる。
最後に決定木分類器クラスを作ってデータへの学習と予測メソッドを設定する
最後にIrisデータセットで学習してみると、
Depth: 0, Sep at Feature: 2,Threshold: 3.0, Label: 2 Depth: 1, Sep at Feature: 2,Threshold: 5.0, Label: 2 Depth: 2, Sep at Feature: 2,Threshold: 5.1, Label: 2 Depth: 3, Sep at Feature: None,Threshold: None, Label: 2 Depth: 3, Sep at Feature: 0,Threshold: 6.7, Label: 2 Depth: 2, Sep at Feature: 3,Threshold: 1.7, Label: 1 Depth: 3, Sep at Feature: 1,Threshold: 3.2, Label: 2 Depth: 3, Sep at Feature: None,Threshold: None, Label: 1 Depth: 1, Sep at Feature: None,Threshold: None, Label: 0 Classification accuracy: 0.9777777777777777
のようになり、テストデータに対し98%程の正解率をだしており上手いこと成長しているのがわかる。また、左側のノードは深さが3まで、右側のノードは深さが1で止まっていることがわかる。各特徴量の重要度も求められていて、
のように図示される。petal length (cm)、つまり花びらの長さが一番分類に寄与していることがわかる。
sklearnと比較してみると、
Classification accuracy: 0.9777777777777777
となり、同様の精度まで決定木が成長していることがわかる。
またSkleanのライブラリでは決定木の可視化ツールも用意していて以下のように使える。
'iris-tree.png'