R のデシジョン ツリー: 例を含む分類ツリー

ディシジョン ツリーとは何ですか?

決定木 は、分類と回帰の両方のタスクを実行できる多目的な機械学習アルゴリズムです。これらは非常に強力なアルゴリズムであり、複雑なデータセットに適合させることができます。さらに、決定木はランダムフォレストの基本コンポーネントであり、現在利用可能な最も強力な機械学習アルゴリズムの 1 つです。

R でのデシジョン ツリーのトレーニングと視覚化

R サンプルで最初のデシジョン ツリーを構築するには、このデシジョン ツリー チュートリアルで次のように進めます。

  • ステップ 1: データをインポートする
  • ステップ 2: データセットをクリーンアップする
  • ステップ 3: トレーニング/テスト セットを作成する
  • ステップ 4: モデルを構築する
  • ステップ 5: 予測を立てる
  • ステップ6:パフォーマンスを測定する
  • ステップ 7: ハイパーパラメータを調整する

ステップ 1) データをインポートする

タイタニック号の運命に興味がある場合は、このビデオをご覧ください。 Youtube。 このデータセットの目的は、氷山との衝突後にどの人が生き残る可能性が高いかを予測することです。 データセットには 13 の変数と 1309 の観測値が含まれています。 データセットは変数 X によって順序付けされます。

set.seed(678)
path <- 'https://raw.githubusercontent.com/guru99-edu/R-Programming/master/titanic_data.csv'
titanic <-read.csv(path)
head(titanic)

出力:

##   X pclass survived                                            name    sex
## 1 1      1        1                   Allen, Miss. Elisabeth Walton female
## 2 2      1        1                  Allison, Master. Hudson Trevor   male
## 3 3      1        0                    Allison, Miss. Helen Loraine female
## 4 4      1        0            Allison, Mr. Hudson Joshua Creighton   male
## 5 5      1        0 Allison, Mrs. Hudson J C (Bessie Waldo Daniels) female
## 6 6      1        1                             Anderson, Mr. Harry   male
##       age sibsp parch ticket     fare   cabin embarked
## 1 29.0000     0     0  24160 211.3375      B5        S
## 2  0.9167     1     2 113781 151.5500 C22 C26        S
## 3  2.0000     1     2 113781 151.5500 C22 C26        S
## 4 30.0000     1     2 113781 151.5500 C22 C26        S
## 5 25.0000     1     2 113781 151.5500 C22 C26        S
## 6 48.0000     0     0  19952  26.5500     E12        S
##                         home.dest
## 1                    St Louis, MO
## 2 Montreal, PQ / Chesterville, ON
## 3 Montreal, PQ / Chesterville, ON
## 4 Montreal, PQ / Chesterville, ON
## 5 Montreal, PQ / Chesterville, ON
## 6                    New York, NY
tail(titanic)

出力:

##         X pclass survived                      name    sex  age sibsp
## 1304 1304      3        0     Yousseff, Mr. Gerious   male   NA     0
## 1305 1305      3        0      Zabour, Miss. Hileni female 14.5     1
## 1306 1306      3        0     Zabour, Miss. Thamine female   NA     1
## 1307 1307      3        0 Zakarian, Mr. Mapriededer   male 26.5     0
## 1308 1308      3        0       Zakarian, Mr. Ortin   male 27.0     0
## 1309 1309      3        0        Zimmerman, Mr. Leo   male 29.0     0
##      parch ticket    fare cabin embarked home.dest
## 1304     0   2627 14.4583              C          
## 1305     0   2665 14.4542              C          
## 1306     0   2665 14.4542              C          
## 1307     0   2656  7.2250              C          
## 1308     0   2670  7.2250              C          
## 1309     0 315082  7.8750              S

先頭と末尾の出力から、データがシャッフルされていないことがわかります。 これは大きな問題です! データをトレイン セットとテスト セットに分割する場合、次を選択します。 クラス 1 と 2 の乗客 (クラス 3 の乗客は観測結果の上位 80% に含まれていません)。これは、アルゴリズムがクラス 3 の乗客の特徴を決して認識しないことを意味します。この間違いにより、予測が不十分になります。

この問題を解決するには、sample() 関数を使用します。

shuffle_index <- sample(1:nrow(titanic))
head(shuffle_index)

決定木Rコード 説明

  • sample(1:nrow(titanic)): 1 ~ 1309 (つまり、最大行数) のインデックスのランダムなリストを生成します。

出力:

## [1]  288  874 1078  633  887  992

このインデックスを使用して、タイタニック データセットをシャッフルします。

titanic <- titanic[shuffle_index, ]
head(titanic)

出力:

##         X pclass survived
## 288   288      1        0
## 874   874      3        0
## 1078 1078      3        1
## 633   633      3        0
## 887   887      3        1
## 992   992      3        1
##                                                           name    sex age
## 288                                      Sutton, Mr. Frederick   male  61
## 874                   Humblen, Mr. Adolf Mathias Nicolai Olsen   male  42
## 1078                                 O'Driscoll, Miss. Bridget female  NA
## 633  Andersson, Mrs. Anders Johan (Alfrida Konstantia Brogren) female  39
## 887                                        Jermyn, Miss. Annie female  NA
## 992                                           Mamee, Mr. Hanna   male  NA
##      sibsp parch ticket    fare cabin embarked           home.dest## 288      0     0  36963 32.3208   D50        S     Haddenfield, NJ
## 874      0     0 348121  7.6500 F G63        S                    
## 1078     0     0  14311  7.7500              Q                    
## 633      1     5 347082 31.2750              S Sweden Winnipeg, MN
## 887      0     0  14313  7.7500              Q                    
## 992      0     0   2677  7.2292              C	

ステップ 2) データセットをクリーンアップする

データの構造を見ると、いくつかの変数に NA があることがわかります。 データのクリーンアップは次のように実行します

  • 変数 home.dest、cabin、name、X、ticket をドロップします
  • pclass の因子変数を作成して生き残った
  • NAをドロップする
library(dplyr)
# Drop variables
clean_titanic <- titanic % > %
select(-c(home.dest, cabin, name, X, ticket)) % > % 
#Convert to factor level
	mutate(pclass = factor(pclass, levels = c(1, 2, 3), labels = c('Upper', 'Middle', 'Lower')),
	survived = factor(survived, levels = c(0, 1), labels = c('No', 'Yes'))) % > %
na.omit()
glimpse(clean_titanic)

コードの説明

  • select(-c(home.dest, Cabinet, name, X, ticket)): 不要な変数を削除します
  • pclass =actor(pclass,levels=c(1,2,3),label=c('Upper', 'Middle', 'Lower')): 変数 pclass にラベルを追加します。 1 が上、2 が中、3 が下になります
  • 因子(生存、レベル = c(0,1)、ラベル = c('いいえ'、'はい')): 変数生存にラベルを追加します。 1 は「いいえ」になり、2 は「はい」になります。
  • na.omit(): NA 観察を削除します。

出力:

## Observations: 1,045
## Variables: 8
## $ pclass   <fctr> Upper, Lower, Lower, Upper, Middle, Upper, Middle, U...
## $ survived <fctr> No, No, No, Yes, No, Yes, Yes, No, No, No, No, No, Y...
## $ sex      <fctr> male, male, female, female, male, male, female, male...
## $ age      <dbl> 61.0, 42.0, 39.0, 49.0, 29.0, 37.0, 20.0, 54.0, 2.0, ...
## $ sibsp    <int> 0, 0, 1, 0, 0, 1, 0, 0, 4, 0, 0, 1, 1, 0, 0, 0, 1, 1,...
## $ parch    <int> 0, 0, 5, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 2, 0, 4, 0,...
## $ fare     <dbl> 32.3208, 7.6500, 31.2750, 25.9292, 10.5000, 52.5542, ...
## $ embarked <fctr> S, S, S, S, S, S, S, S, S, C, S, S, S, Q, C, S, S, C...		

ステップ 3) トレーニング/テスト セットを作成する

モデルをトレーニングする前に、次の XNUMX つの手順を実行する必要があります。

  • トレーニング セットとテスト セットを作成する: トレーニング セットでモデルをトレーニングし、テスト セットで予測をテストします (つまり、未確認のデータ)。
  • コンソールから rpart.plot をインストールします

一般的な方法は、データを 80/20 に分割し、データの 80 パーセントをモデルのトレーニングに使用し、20 パーセントを予測に使用することです。 XNUMX つの別々のデータ フレームを作成する必要があります。 モデルの構築が完了するまでは、テスト セットには触れたくないでしょう。 XNUMX つの引数を取る関数名 create_train_test() を作成できます。

create_train_test(df, size = 0.8, train = TRUE)
arguments:
-df: Dataset used to train the model.
-size: Size of the split. By default, 0.8. Numerical value
-train: If set to `TRUE`, the function creates the train set, otherwise the test set. Default value sets to `TRUE`. Boolean value.You need to add a Boolean parameter because R does not allow to return two data frames simultaneously.
create_train_test <- function(data, size = 0.8, train = TRUE) {
    n_row = nrow(data)
    total_row = size * n_row
    train_sample < - 1: total_row
    if (train == TRUE) {
        return (data[train_sample, ])
    } else {
        return (data[-train_sample, ])
    }
}

コードの説明

  • function(data, size=0.8, train = TRUE): 関数に引数を追加します
  • n_row = nrow(data): データセット内の行数をカウントします。
  • total_row = size*n_row: 列車セットを構築するために n 番目の行を返します。
  • train_sample <- 1:total_row: XNUMX行目からn行目までを選択
  • if (train ==TRUE){ } else { }: 条件が true に設定されている場合は、トレーニング セットを返し、それ以外の場合はテスト セットを返します。

機能をテストして寸法を確認できます。

data_train <- create_train_test(clean_titanic, 0.8, train = TRUE)
data_test <- create_train_test(clean_titanic, 0.8, train = FALSE)
dim(data_train)

出力:

## [1] 836   8
dim(data_test)

出力:

## [1] 209   8

トレーニング データセットには 1046 行があり、テスト データセットには 262 行があります。

関数 prop.table() を table() と組み合わせて使用​​して、ランダム化プロセスが正しいかどうかを確認します。

prop.table(table(data_train$survived))

出力:

##
##        No       Yes 
## 0.5944976 0.4055024
prop.table(table(data_test$survived))

出力:

## 
##        No       Yes 
## 0.5789474 0.4210526

どちらのデータセットでも、生存者の数は同じで、約 40 パーセントです。

rpart.plot をインストールする

rpart.plot は conda ライブラリからは利用できません。 コンソールからインストールできます。

install.packages("rpart.plot")

ステップ 4) モデルを構築する

モデルを構築する準備ができました。 Rpart デシジョン ツリー関数の構文は次のとおりです。

rpart(formula, data=, method='')
arguments:			
- formula: The function to predict
- data: Specifies the data frame- method: 			
- "class" for a classification tree 			
- "anova" for a regression tree	

クラスを予測するため、クラス メソッドを使用します。

library(rpart)
library(rpart.plot)
fit <- rpart(survived~., data = data_train, method = 'class')
rpart.plot(fit, extra = 106

コードの説明

  • rpart(): モデルに適合する関数。 引数は次のとおりです。
    • 生き残った ~.: ディシジョン ツリーの公式
    • data = data_train: データセット
    • Method = 'class': バイナリ モデルを当てはめる
  • rpart.plot(fit, extra= 106): ツリーをプロットします。 追加の特徴は、101 番目のクラスの確率を表示するために 2 に設定されています (二値応答に役立ちます)。 を参照できます。 ビネット 他の選択肢について詳しくは、こちらをご覧ください。

出力:

R で決定木のモデルを構築する

ルート ノード (深さ 0 から 3、グラフの上部) から開始します。

  1. 一番上は全体的な生存確率です。 事故で生き残った乗客の割合を示します。 乗客の41パーセントが生存した。
  2. このノードは、乗客の性別が男性であるかどうかを尋ねます。 「はい」の場合は、ルートの左側の子ノード (深さ 2) に進みます。 63%は男性で、生存確率は21%です。
  3. 3.5 番目のノードでは、男性乗客の年齢が 19 歳以上かどうかを尋ねます。 もしそうなら、生存の可能性はXNUMXパーセントです。
  4. どのような特徴が生存の可能性に影響を与えるかを理解するために、このような作業を続けます。

デシジョン ツリーの多くの特徴の XNUMX つは、データの準備がほとんど必要ないことです。 特に、フィーチャのスケーリングやセンタリングは必要ありません。

デフォルトでは、rpart() 関数は ジーニ ノートを分割するための不純物メジャー。 ジニ係数が高いほど、ノード内の異なるインスタンスが多くなります。

ステップ 5) 予測を立てる

テスト データセットを予測できます。 予測を行うには、predict() 関数を使用できます。 R デシジョン ツリーの予測の基本的な構文は次のとおりです。

predict(fitted_model, df, type = 'class')
arguments:
- fitted_model: This is the object stored after model estimation. 
- df: Data frame used to make the prediction
- type: Type of prediction			
    - 'class': for classification			
    - 'prob': to compute the probability of each class			
    - 'vector': Predict the mean response at the node level	

テスト セットから、衝突後にどの乗客が生き残る可能性が高いかを予測したいと考えています。 つまり、209 人の乗客のうち、誰が生き残るかどうかがわかるということです。

predict_unseen <-predict(fit, data_test, type = 'class')

コードの説明

  • detect(fit, data_test, type = 'class'): テスト セットのクラス (0/1) を予測します。

到着できなかった乗客と到着した乗客を検査する。

table_mat <- table(data_test$survived, predict_unseen)
table_mat

コードの説明

  • table(data_test$survived, detect_unseen): R の正しいデシジョン ツリー分類と比較して、生存者として分類され死亡した乗客の数をカウントするテーブルを作成します。

出力:

##      predict_unseen
##        No Yes
##   No  106  15
##   Yes  30  58

モデルは 106 人の死亡乗客を正確に予測しましたが、15 人の生存者を死亡として分類しました。 類推すると、モデルは 30 人の乗客を生存者として誤分類しましたが、彼らは死亡していることが判明しました。

ステップ 6) パフォーマンスを測定する

分類タスクの精度尺度を計算するには、 混同行列:

この 混同行列 分類パフォーマンスを評価するには、これがより良い選択です。 一般的な考え方は、True インスタンスが False に分類される回数をカウントすることです。

R の決定木のパフォーマンスを測定する

混同行列の各行は実際のターゲットを表し、各列は予測されたターゲットを表します。 この行列の最初の行では、死亡した乗客 (False クラス) が考慮されます。106 人が死亡したと正しく分類されました (真陰性)、残りの XNUMX 人は誤って生存者として分類されました (偽陽性)。 58 行目は生存者を考慮しており、陽性クラスは XNUMX 人でした (真陽性)、 真陰性 30でした。

計算できます 精度テスト 混同行列から:

R の決定木のパフォーマンスを測定する

これは、行列の合計に対する真の陽性と真の陰性の割合です。 R を使用すると、次のようにコーディングできます。

accuracy_Test <- sum(diag(table_mat)) / sum(table_mat)

コードの説明

  • sum(diag(table_mat)): 対角線の合計
  • sum(table_mat): 行列の合計。

テスト セットの精度を出力できます。

print(paste('Accuracy for test', accuracy_Test))

出力:

## [1] "Accuracy for test 0.784688995215311"

テストセットのスコアは 78% です。 トレーニング データセットを使用して同じ演習を複製できます。

ステップ 7) ハイパーパラメータを調整する

Rの決定木には、フィットのさまざまな側面を制御するさまざまなパラメータがあります。rpart決定木ライブラリでは、rpart.control()関数を使用してパラメータを制御できます。次のコードでは、調整するパラメータを導入しています。 ビネット 他のパラメータについては。

rpart.control(minsplit = 20, minbucket = round(minsplit/3), maxdepth = 30)
Arguments:
-minsplit: Set the minimum number of observations in the node before the algorithm perform a split
-minbucket:  Set the minimum number of observations in the final note i.e. the leaf
-maxdepth: Set the maximum depth of any node of the final tree. The root node is treated a depth 0

以下のように進めていきます。

  • 精度を返す関数を構築する
  • 最大深度を調整する
  • ノードを分割する前にノードに必要なサンプルの最小数を調整します。
  • リーフノードに必要なサンプルの最小数を調整する

精度を表示する関数を作成できます。 以前に使用したコードをラップするだけです。

  1. 予測:predict_unseen <- 予測(fit, data_test, type = 'class')
  2. テーブルの生成: table_mat <- table(data_test$survived, detect_unseen)
  3. 精度の計算:accuracy_Test <- sum(diag(table_mat))/sum(table_mat)
accuracy_tune <- function(fit) {
    predict_unseen <- predict(fit, data_test, type = 'class')
    table_mat <- table(data_test$survived, predict_unseen)
    accuracy_Test <- sum(diag(table_mat)) / sum(table_mat)
    accuracy_Test
}

パラメーターを調整して、モデルをデフォルト値よりも改善できるかどうかを確認できます。 0.78 より高い精度を得る必要があることに注意してください。

control <- rpart.control(minsplit = 4,
    minbucket = round(5 / 3),
    maxdepth = 3,
    cp = 0)
tune_fit <- rpart(survived~., data = data_train, method = 'class', control = control)
accuracy_tune(tune_fit)

出力:

## [1] 0.7990431

次のパラメータを使用します。

minsplit = 4
minbucket= round(5/3)
maxdepth = 3cp=0

前モデルよりもさらに高いパフォーマンスが得られます。 おめでとうございます!

まとめ

決定木アルゴリズムを訓練するための関数をまとめると、 R

図書室へようこそ DevOps Tools Engineer試験のObjective 演算 CLASS 計測パラメータ 詳細
パーツ R で分類ツリーを訓練する rpart() class 式、DF、メソッド
パーツ 回帰ツリーを訓練する rpart() 分散分析 式、DF、メソッド
パーツ 木を植える rpart.plot() フィットモデル
ベース 予測する predict() class 適合モデル、タイプ
ベース 予測する predict() PROB 適合モデル、タイプ
ベース 予測する predict() ベクトル 適合モデル、タイプ
パーツ 制御パラメータ rpart.control() ミンスプリット アルゴリズムが分割を実行する前に、ノード内の観測の最小数を設定します。
最小バケット 最後のノート、つまりリーフに観測値の最小数を設定します。
最大深度 最終ツリーのノードの最大深さを設定します。 ルートノードは深さ0として扱われます
パーツ 制御パラメーターを使用してモデルをトレーニングする rpart() 数式、DF、メソッド、コントロール

注: トレーニング データでモデルをトレーニングし、目に見えないデータセット、つまりテスト セットでパフォーマンスをテストします。