CART:不純物減少の増加が等しい場合の分割に最適な予測子の選択?


8

私の質問は分類木を扱っています。Irisデータセットの次の例を考えてみます。

ここに画像の説明を入力してください

最初の分割に最適な予測子を手動で選択したい。CARTアルゴリズムによると、分割を行うための最良の機能は、パーティションの不純性の減少を最大化する機能であり、ジニゲインとも呼ばれます。

GGaNバツ=GN|N1||N|GN1|N2||N|GN1

ここで、与えられた機能であり、分割がなされるべきでノードであり、と分割することによって作成された2つのつの子ノードである。は、ノードの要素数です。バツNN1N2N||

そして、。ここで、はノード内のカテゴリの数です KGN=1Σk=1Kpk2K

ここで、花びらの幅(軸#1)と花びらの長さ(軸#2)に基づいて分割すると、同じパーティションが生成されるため(すべてのSetosa花が非Setosaから分離されます)、GinGainスコアはそれぞれに対してまったく同じになります予測因子。では、CARTアルゴリズムはどのアルゴリズムが最適かをどのように決定するのでしょうか。

直感的に、花弁の長さ(2)での分割は最大の "マージン"に関連付けられていることがわかります。したがって、花弁の長さを選択する必要があります(実際にrpartはRで実装すると何が起こるか)が、マージンを測定しないため、決定他のものに基づいている必要があります。GGa

関連スレッドですが、私の質問への答えはありません。

回答のない関連スレッド

回答:


8

私は平凡なcコードインタープリターであることを告白しますが、この古いコードはユーザーフレンドリーではありません。そうは言っても、私はソースコードを調べてこれらの観察を行ったので、「rpartは文字通り、最初の最適な変数列を選択する」と確信することができました。列1と2は下位の分割を生成するため、この列はdata.frame / matrixのpetal.widthの前にあるため、petal.lengthは最初に分割変数になります。最後に、petal.withが最初に分割変数になるように列の順序を逆にすることでこれを示します。

Cソースファイルの「bsplit.c」のrpartのソースコードで、 38行目から引用します。

 * test out the variables 1 at at time
me->primary = (pSplit) NULL;
for (i = 0; i < rp.nvar; i++) {

...したがって、i = 1からrp.nvarで始まるforループで反復すると、1つの変数ですべての分割をスキャンするために損失関数が呼び出されます。新しい分割の方が良い場合は更新されます。(これは、ユーザー定義の損失関数の場合もあります)

if (temp < best) {
        best = temp;
        where = i;
        direction = lmean < rmean ? LEFT : RIGHT;
}

最後の行323では、変数による最良の分割の改善が計算されます...

*improve = total_ss - best

... bsplit.cに戻って、以前に見られたよりも大きい場合は改善がチェックされ、大きい場合にのみ更新されます。

if (improve > rp.iscale)
rp.iscale = improve;        /* largest seen so far */

これに対する私の印象は、新しいブレークポイントがより良いスコアを持っている場合にのみ保存されるため、(可能なタイの)最初で最良のものが選択されるということです。これは、最初に見つかった最高のブレークポイントと最初に見つかった最高の変数の両方に関係します。ブレークポイントは、gini.cで単純に左から右にスキャンされていないようです。そのため、最初に見つかった結合ブレークポイントは、予測が難しい場合があります。ただし、変数は最初の列から最後の列までスキャンすることで非常に予測可能です。

この動作は、classTree.cで次のソリューションが使用されるrandomForest実装とは異なります。

/* Break ties at random: */
if (crit == critmax) {
    if (unif_rand() < 1.0 / ntie) {
        *bestSplit = j;
        critmax = crit;
        *splitVar = mvar;
    }
    ntie++;
}

最後に、petal.widthが最初に選択されるように、アイリスの列を反転してこの動作を確認します

library(rpart)
data(iris)
iris = iris[,5:1]  #flip/flop", invert order of columns columns
obj = rpart(Species~.,data=iris)
print(obj) #now petal width is first split 


1) root 150 100 setosa (0.33333333 0.33333333 0.33333333)  
  2) Petal.Width< 0.8 50   0 setosa (1.00000000 0.00000000 0.00000000) *
  3) Petal.Width>=0.8 100  50 versicolor (0.00000000 0.50000000 0.50000000)  
    6) Petal.Width< 1.75 54   5 versicolor (0.00000000 0.90740741 0.09259259) *
    7) Petal.Width>=1.75 46   1 virginica (0.00000000 0.02173913 0.97826087) *

...そして再び元に戻す

iris = iris[,5:1]  #flop/flip", revert order of columns columns
obj = rpart(Species~.,data=iris)
print(obj) #now petal length is first split 
1) root 150 100 setosa (0.33333333 0.33333333 0.33333333)  
  2) Petal.Length< 2.45 50   0 setosa (1.00000000 0.00000000 0.00000000) *
  3) Petal.Length>=2.45 100  50 versicolor (0.00000000 0.50000000 0.50000000)  
    6) Petal.Width< 1.75 54   5 versicolor (0.00000000 0.90740741 0.09259259) *
    7) Petal.Width>=1.75 46   1 virginica (0.00000000 0.02173913 0.97826087) *

ご回答どうもありがとうございました。したがって、複数の予測子が最適な分割に対応する場合、最初の予測子が選択されますが、これはマージンとはまったく関係ありません。結局のところ、一種の理にかなっています。
アントワーヌ

バイナリスプリットは
本来

rpartのソースコードはを介してRコンソールから取得し、現在の作業ディレクトリのフォルダーを(このSO スレッドから)開くこともできるので、参考にしuntar(download.packages(pkgs = "rpart",destdir = ".",type = "source")[,2])srcください。次に、特定の関数のコードをNotepad ++で表示できます。
アントワーヌ

そして、分割がすべてのノードに対してもはや改善をもたらさないとき、アルゴリズムは停止しますよね?
アントワーヌ

うん。partition.cの80行目isch:「これはかなりまれですが、実行する価値のある分割を見つけることができませんでした」...なりすましの再帰関数によると その後、ノードは封印され、前のノードへの再帰的アルゴリズムreturnはreturn(0)を呼び出します。
Soren Havelundウェリング
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.