1. 程式人生 > >R語言(遞迴分割樹[傳統決策樹])分類模型(一)

R語言(遞迴分割樹[傳統決策樹])分類模型(一)

簡介

分類演算法是基於類標號已知的訓練資料集建立分類模型並使用其對新觀測值(測試資料集)進行分類的演算法,因而也和迴歸一樣屬於監督學習演算法,都是使用訓練集的已知結論(類標號)預測測試資料集的分類結果,分類與迴歸的最大區別是後者對連續值進行處理。
我們先使用churn資料集分別建立訓練資料集和測試資料集,然後使用不用的分類模型對其分類。緊接著使用傳統分類樹與條件推理樹來介紹基於樹的分類方法,還將介紹基於延遲與基於概率的演算法。這些演算法都會基於訓練資料建立分類資料集,然後利用分類模型建立預測測試資料的分類結果,我們還將構建一個混淆矩陣來評測這些模型的預測效能。

準備訓練與測試資料集

使用C50包中的客戶流失資料(churn資料集),有3333個樣例,資料維度為20,我們建立一個分類模型判斷客戶是否會流失,因為爭取一個新客戶的成本要小於一維護一個老客戶,因此預測的結果就比較重要。
在建立模型時,首先對資料進行預處理,通過觀測state、area_code、account_length對建模分類沒有作用,因此先去掉這三個屬性。
完成預處後將資料集分為訓練和測試兩個集合,我們使用一個樣本隨機函式生成一個序列,序列大小等於70%的樣例大小,再生成一個大小等於30%的樣例序列。

library(grid)
library(partykit)
library(C50)

data(churn)

str(churnTrain)
'data.frame':   3333 obs. of  20 variables:
 $ state                        : Factor w/ 51 levels "AK","AL","AR",..: 17 36 32 36 37 2 20 25 19 50 ...
 $ account_length               : int  128 107 137 84 75 118 121 147 117 141 ...
$ area_code : Factor w/ 3 levels "area_code_408",..: 2 2 2 1 2 3 3 2 1 2 ... $ international_plan : Factor w/ 2 levels "no","yes": 1 1 1 2 2 2 1 2 1 2 ... $ voice_mail_plan : Factor w/ 2 levels "no","yes": 2 2 1 1 1 1 2 1 1 2 ... $ number_vmail_messages : int 25
26 0 0 0 0 24 0 0 37 ... $ total_day_minutes : num 265 162 243 299 167 ... $ total_day_calls : int 110 123 114 71 113 98 88 79 97 84 ... $ total_day_charge : num 45.1 27.5 41.4 50.9 28.3 ... $ total_eve_minutes : num 197.4 195.5 121.2 61.9 148.3 ... $ total_eve_calls : int 99 103 110 88 122 101 108 94 80 111 ... $ total_eve_charge : num 16.78 16.62 10.3 5.26 12.61 ... $ total_night_minutes : num 245 254 163 197 187 ... $ total_night_calls : int 91 103 104 89 121 118 118 96 90 97 ... $ total_night_charge : num 11.01 11.45 7.32 8.86 8.41 ... $ total_intl_minutes : num 10 13.7 12.2 6.6 10.1 6.3 7.5 7.1 8.7 11.2 ... $ total_intl_calls : int 3 3 5 7 3 6 7 6 4 5 ... $ total_intl_charge : num 2.7 3.7 3.29 1.78 2.73 1.7 2.03 1.92 2.35 3.02 ... $ number_customer_service_calls: int 1 1 0 2 3 0 3 0 1 0 ... $ churn : Factor w/ 2 levels "yes","no": 2 2 2 2 2 2 2 2 2 2 ... churnTrain = churnTrain[,!names(churnTrain) %in% c("state","area_code","account_length")] #生成隨機編號為2的隨機數 set.seed(2) #將churnTrain的資料集分為兩類,按0.7與0.3的比例無放回抽樣 ind = sample(2,nrow(churnTrain),replace = TRUE,prob = c(0.7,0.3)) trainset = churnTrain[ind == 1,] testset = churnTrain[ind == 2,] dim(trainset) [1] 2315 17 dim(testset) [1] 1018 17

使用遞迴分割樹建立分類模型

分類樹對分類結果的預測是基於一個或者多個輸入變數並結合劃分條件完成的。分裂過程從分類樹樹根結點開始:在每一個節點,演算法將根據劃分條件檢查輸入變數是否需要斷續向左子葉樹與右子葉樹遞迴進行劃分,當達到任意分類樹的子節點(終點)時,停止分裂。

churn.rp = rpart(churn ~ .,data = trainset)

churn.rp
n= 2315 

node), split, n, loss, yval, (yprob)
      * denotes terminal node

 1) root 2315 342 no (0.14773218 0.85226782)  
   2) total_day_minutes>=265.45 144  59 yes (0.59027778 0.40972222)  
     4) voice_mail_plan=no 110  29 yes (0.73636364 0.26363636)  
       8) total_eve_minutes>=188.5 67   3 yes (0.95522388 0.04477612) *
       9) total_eve_minutes< 188.5 43  17 no (0.39534884 0.60465116)  
        18) total_day_minutes>=282.7 19   6 yes (0.68421053 0.31578947) *
        19) total_day_minutes< 282.7 24   4 no (0.16666667 0.83333333) *
     5) voice_mail_plan=yes 34   4 no (0.11764706 0.88235294) *
   3) total_day_minutes< 265.45 2171 257 no (0.11837863 0.88162137)  
     6) number_customer_service_calls>=3.5 168  82 yes (0.51190476 0.48809524)  
      12) total_day_minutes< 160.2 71  10 yes (0.85915493 0.14084507) *
      13) total_day_minutes>=160.2 97  25 no (0.25773196 0.74226804)  
        26) total_eve_minutes< 155.5 20   7 yes (0.65000000 0.35000000) *
        27) total_eve_minutes>=155.5 77  12 no (0.15584416 0.84415584) *
     7) number_customer_service_calls< 3.5 2003 171 no (0.08537194 0.91462806)  
      14) international_plan=yes 188  76 no (0.40425532 0.59574468)  
        28) total_intl_calls< 2.5 38   0 yes (1.00000000 0.00000000) *
        29) total_intl_calls>=2.5 150  38 no (0.25333333 0.74666667)  
          58) total_intl_minutes>=13.1 32   0 yes (1.00000000 0.00000000) *
          59) total_intl_minutes< 13.1 118   6 no (0.05084746 0.94915254) *
      15) international_plan=no 1815  95 no (0.05234160 0.94765840)  
        30) total_day_minutes>=224.15 251  50 no (0.19920319 0.80079681)  
          60) total_eve_minutes>=259.8 36  10 yes (0.72222222 0.27777778) *
          61) total_eve_minutes< 259.8 215  24 no (0.11162791 0.88837209) *
        31) total_day_minutes< 224.15 1564  45 no (0.02877238 0.97122762) *

接下來,呼叫printcp來檢查複雜性引數

printcp(churn.rp)

Classification tree:
rpart(formula = churn ~ ., data = trainset)

Variables actually used in tree construction:
[1] international_plan            number_customer_service_calls
[3] total_day_minutes             total_eve_minutes            
[5] total_intl_calls              total_intl_minutes           
[7] voice_mail_plan              

Root node error: 342/2315 = 0.14773

n= 2315 

        CP nsplit rel error  xerror     xstd
1 0.076023      0   1.00000 1.00000 0.049920
2 0.074561      2   0.84795 0.99708 0.049860
3 0.055556      4   0.69883 0.76023 0.044421
4 0.026316      7   0.49415 0.52632 0.037673
5 0.023392      8   0.46784 0.52047 0.037481
6 0.020468     10   0.42105 0.50877 0.037092
7 0.017544     11   0.40058 0.47076 0.035788
8 0.010000     12   0.38304 0.47661 0.035993
plotcp(churn.rp)

成本複雜性函式

成本複雜性函式
最後使用summary檢查已經建立的模型

 summary(churn.rp)
Call:
rpart(formula = churn ~ ., data = trainset)
  n= 2315 

          CP nsplit rel error    xerror       xstd
1 0.07602339      0 1.0000000 1.0000000 0.04992005
2 0.07456140      2 0.8479532 0.9590643 0.04906076
3 0.05555556      4 0.6988304 0.7953216 0.04530196
4 0.02631579      7 0.4941520 0.5233918 0.03757730
5 0.02339181      8 0.4678363 0.5263158 0.03767329
6 0.02046784     10 0.4210526 0.5175439 0.03738427
7 0.01754386     11 0.4005848 0.5058480 0.03699399
8 0.01000000     12 0.3830409 0.4970760 0.03669750

Variable importance
            total_day_minutes              total_day_charge number_customer_service_calls 
                           18                            18                            10 
           total_intl_minutes             total_intl_charge              total_eve_charge 
                            8                             8                             8 
            total_eve_minutes            international_plan              total_intl_calls 
                            8                             7                             6 
        number_vmail_messages               voice_mail_plan             total_night_calls 
                            3                             3                             1 
              total_eve_calls 
                            1 

Node number 1: 2315 observations,    complexity param=0.07602339
  predicted class=no   expected loss=0.1477322  P(node) =1
    class counts:   342  1973
   probabilities: 0.148 0.852 
  left son=2 (144 obs) right son=3 (2171 obs)
  Primary splits:
      total_day_minutes             < 265.45 to the right, improve=60.145020, (0 missing)
      total_day_charge              < 45.125 to the right, improve=60.145020, (0 missing)
      number_customer_service_calls < 3.5    to the right, improve=53.641430, (0 missing)
      international_plan            splits as  RL,         improve=43.729370, (0 missing)
      voice_mail_plan               splits as  LR,         improve= 6.089388, (0 missing)
  Surrogate splits:
      total_day_charge < 45.125 to the right, agree=1, adj=1, (0 split)

Node number 2: 144 observations,    complexity param=0.07602339
  predicted class=yes  expected loss=0.4097222  P(node) =0.06220302
    class counts:    85    59
   probabilities: 0.590 0.410 
  left son=4 (110 obs) right son=5 (34 obs)
  Primary splits:
      voice_mail_plan       splits as  LR,         improve=19.884860, (0 missing)
      number_vmail_messages < 9.5    to the left,  improve=19.884860, (0 missing)
      total_eve_minutes     < 167.05 to the right, improve=14.540020, (0 missing)
      total_eve_charge      < 14.2   to the right, improve=14.540020, (0 missing)
      total_day_minutes     < 283.9  to the right, improve= 6.339827, (0 missing)
  Surrogate splits:
      number_vmail_messages < 9.5    to the left,  agree=1.000, adj=1.000, (0 split)
      total_night_minutes   < 110.3  to the right, agree=0.785, adj=0.088, (0 split)
      total_night_charge    < 4.965  to the right, agree=0.785, adj=0.088, (0 split)
      total_night_calls     < 50     to the right, agree=0.778, adj=0.059, (0 split)
      total_intl_minutes    < 15.3   to the left,  agree=0.771, adj=0.029, (0 split)

Node number 3: 2171 observations,    complexity param=0.0745614
  predicted class=no   expected loss=0.1183786  P(node) =0.937797
    class counts:   257  1914
   probabilities: 0.118 0.882 
  left son=6 (168 obs) right son=7 (2003 obs)
  Primary splits:
      number_customer_service_calls < 3.5    to the right, improve=56.398210, (0 missing)
      international_plan            splits as  RL,         improve=43.059160, (0 missing)
      total_day_minutes             < 224.15 to the right, improve=10.847440, (0 missing)
      total_day_charge              < 38.105 to the right, improve=10.847440, (0 missing)
      total_intl_minutes            < 13.15  to the right, improve= 6.347319, (0 missing)

Node number 4: 110 observations,    complexity param=0.02631579
  predicted class=yes  expected loss=0.2636364  P(node) =0.0475162
    class counts:    81    29
   probabilities: 0.736 0.264 
  left son=8 (67 obs) right son=9 (43 obs)
  Primary splits:
      total_eve_minutes   < 188.5  to the right, improve=16.419610, (0 missing)
      total_eve_charge    < 16.025 to the right, improve=16.419610, (0 missing)
      total_night_minutes < 206.85 to the right, improve= 5.350500, (0 missing)
      total_night_charge  < 9.305  to the right, improve= 5.350500, (0 missing)
      total_day_minutes   < 281.15 to the right, improve= 5.254545, (0 missing)
  Surrogate splits:
      total_eve_charge   < 16.025 to the right, agree=1.000, adj=1.000, (0 split)
      total_night_calls  < 82     to the right, agree=0.655, adj=0.116, (0 split)
      total_intl_minutes < 3.35   to the right, agree=0.636, adj=0.070, (0 split)
      total_intl_charge  < 0.905  to the right, agree=0.636, adj=0.070, (0 split)
      total_day_minutes  < 268.55 to the right, agree=0.627, adj=0.047, (0 split)

Node number 5: 34 observations
  predicted class=no   expected loss=0.1176471  P(node) =0.01468683
    class counts:     4    30
   probabilities: 0.118 0.882 

Node number 6: 168 observations,    complexity param=0.0745614
  predicted class=yes  expected loss=0.4880952  P(node) =0.07257019
    class counts:    86    82
   probabilities: 0.512 0.488 
  left son=12 (71 obs) right son=13 (97 obs)
  Primary splits:
      total_day_minutes             < 160.2  to the left,  improve=29.655880, (0 missing)
      total_day_charge              < 27.235 to the left,  improve=29.655880, (0 missing)
      total_eve_minutes             < 180.65 to the left,  improve= 8.556953, (0 missing)
      total_eve_charge              < 15.355 to the left,  improve= 8.556953, (0 missing)
      number_customer_service_calls < 4.5    to the right, improve= 5.975362, (0 missing)
  Surrogate splits:
      total_day_charge              < 27.235 to the left,  agree=1.000, adj=1.000, (0 split)
      total_night_calls             < 79     to the left,  agree=0.625, adj=0.113, (0 split)
      total_intl_calls              < 2.5    to the left,  agree=0.619, adj=0.099, (0 split)
      number_customer_service_calls < 4.5    to the right, agree=0.607, adj=0.070, (0 split)
      total_eve_calls               < 89.5   to the left,  agree=0.601, adj=0.056, (0 split)

Node number 7: 2003 observations,    complexity param=0.05555556
  predicted class=no   expected loss=0.08537194  P(node) =0.8652268
    class counts:   171  1832
   probabilities: 0.085 0.915 
  left son=14 (188 obs) right son=15 (1815 obs)
  Primary splits:
      international_plan splits as  RL,         improve=42.194510, (0 missing)
      total_day_minutes  < 224.15 to the right, improve=16.838410, (0 missing)
      total_day_charge   < 38.105 to the right, improve=16.838410, (0 missing)
      total_intl_minutes < 13.15  to the right, improve= 6.210678, (0 missing)
      total_intl_charge  < 3.55   to the right, improve= 6.210678, (0 missing)

Node number 8: 67 observations
  predicted class=yes  expected loss=0.04477612  P(node) =0.02894168
    class counts:    64     3
   probabilities: 0.955 0.045 

Node number 9: 43 observations,    complexity param=0.02046784
  predicted class=no   expected loss=0.3953488  P(node) =0.01857451
    class counts:    17    26
   probabilities: 0.395 0.605 
  left son=18 (19 obs) right son=19 (24 obs)
  Primary splits:
      total_day_minutes   < 282.7  to the right, improve=5.680947, (0 missing)
      total_day_charge    < 48.06  to the right, improve=5.680947, (0 missing)
      total_night_minutes < 212.65 to the right, improve=4.558140, (0 missing)
      total_night_charge  < 9.57   to the right, improve=4.558140, (0 missing)
      total_eve_minutes   < 145.4  to the right, improve=4.356169, (0 missing)
  Surrogate splits:
      total_day_charge   < 48.06  to the right, agree=1.000, adj=1.000, (0 split)
      total_day_calls    < 103    to the left,  agree=0.674, adj=0.263, (0 split)
      total_eve_calls    < 104.5  to the left,  agree=0.674, adj=0.263, (0 split)
      total_intl_minutes < 11.55  to the left,  agree=0.651, adj=0.211, (0 split)
      total_intl_charge  < 3.12   to the left,  agree=0.651, adj=0.211, (0 split)

Node number 12: 71 observations
  predicted class=yes  expected loss=0.1408451  P(node) =0.03066955
    class counts:    61    10
   probabilities: 0.859 0.141 

Node number 13: 97 observations,    complexity param=0.01754386
  predicted class=no   expected loss=0.257732  P(node) =0.04190065
    class counts:    25    72
   probabilities: 0.258 0.742 
  left son=26 (20 obs) right son=27 (77 obs)
  Primary splits:
      total_eve_minutes             < 155.5  to the left,  improve=7.753662, (0 missing)
      total_eve_charge              < 13.22  to the left,  improve=7.753662, (0 missing)
      total_intl_minutes            < 13.55  to the right, improve=2.366149, (0 missing)
      total_intl_charge             < 3.66   to the right, improve=2.366149, (0 missing)
      number_customer_service_calls < 4.5    to the right, improve=2.297667, (0 missing)
  Surrogate splits:
      total_eve_charge  < 13.22  to the left,  agree=1.000, adj=1.00, (0 split)
      total_night_calls < 143.5  to the right, agree=0.814, adj=0.10, (0 split)
      total_eve_calls   < 62     to the left,  agree=0.804, adj=0.05, (0 split)

Node number 14: 188 observations,    complexity param=0.05555556
  predicted class=no   expected loss=0.4042553  P(node) =0.0812095
    class counts:    76   112
   probabilities: 0.404 0.596 
  left son=28 (38 obs) right son=29 (150 obs)
  Primary splits:
      total_intl_calls   < 2.5    to the left,  improve=33.806520, (0 missing)
      total_intl_minutes < 13.1   to the right, improve=30.527050, (0 missing)
      total_intl_charge  < 3.535  to the right, improve=30.527050, (0 missing)
      total_day_minutes  < 221.95 to the right, improve= 3.386095, (0 missing)
      total_day_charge   < 37.735 to the right, improve= 3.386095, (0 missing)

Node number 15: 1815 observations,    complexity param=0.02339181
  predicted class=no   expected loss=0.0523416  P(node) =0.7840173
    class counts:    95  1720
   probabilities: 0.052 0.948 
  left son=30 (251 obs) right son=31 (1564 obs)
  Primary splits:
      total_day_minutes   < 224.15 to the right, improve=12.5649300, (0 missing)
      total_day_charge    < 38.105 to the right, improve=12.5649300, (0 missing)
      total_eve_minutes   < 244.95 to the right, improve= 4.7875890, (0 missing)
      total_eve_charge    < 20.825 to the right, improve= 4.7875890, (0 missing)
      total_night_minutes < 163.85 to the right, improve= 0.9074391, (0 missing)
  Surrogate splits:
      total_day_charge < 38.105 to the right, agree=1, adj=1, (0 split)

Node number 18: 19 observations
  predicted class=yes  expected loss=0.3157895  P(node) =0.008207343
    class counts:    13     6
   probabilities: 0.684 0.316 

Node number 19: 24 observations
  predicted class=no   expected loss=0.1666667  P(node) =0.01036717
    class counts:     4    20
   probabilities: 0.167 0.833 

Node number 26: 20 observations
  predicted class=yes  expected loss=0.35  P(node) =0.008639309
    class counts:    13     7
   probabilities: 0.650 0.350 

Node number 27: 77 observations
  predicted class=no   expected loss=0.1558442  P(node) =0.03326134
    class counts:    12    65
   probabilities: 0.156 0.844 

Node number 28: 38 observations
  predicted class=yes  expected loss=0  P(node) =0.01641469
    class counts:    38     0
   probabilities: 1.000 0.000 

Node number 29: 150 observations,    complexity param=0.05555556
  predicted class=no   expected loss=0.2533333  P(node) =0.06479482
    class counts:    38   112
   probabilities: 0.253 0.747 
  left son=58 (32 obs) right son=59 (118 obs)
  Primary splits:
      total_intl_minutes < 13.1   to the right, improve=45.356840, (0 missing)
      total_intl_charge  < 3.535  to the right, improve=45.356840, (0 missing)
      total_day_calls    < 95.5   to the left,  improve= 4.036407, (0 missing)
      total_day_minutes  < 237.75 to the right, improve= 1.879020, (0 missing)
      total_day_charge   < 40.42  to the right, improve= 1.879020, (0 missing)
  Surrogate splits:
      total_intl_charge < 3.535  to the right, agree=1.0, adj=1.000, (0 split)
      total_day_minutes < 52.45  to the left,  agree=0.8, adj=0.063, (0 split)
      total_day_charge  < 8.92   to the left,  agree=0.8, adj=0.063, (0 split)

Node number 30: 251 observations,    complexity param=0.02339181
  predicted class=no   expected loss=0.1992032  P(node) =0.1084233
    class counts:    50   201
   probabilities: 0.199 0.801 
  left son=60 (36 obs) right son=61 (215 obs)
  Primary splits:
      total_eve_minutes     < 259.8  to the right, improve=22.993380, (0 missing)
      total_eve_charge      < 22.08  to the right, improve=22.993380, (0 missing)
      voice_mail_plan       splits as  LR,         improve= 4.745664, (0 missing)
      number_vmail_messages < 7.5