CART算法实现_基于R语言

CART算法(Classification And Regression Tree,分类和回归树)是决策树的一种,由Leo Breiman, Jerome Friedman, Richard Olshen与Charles Stone于1984年提出,既可用于分类也可用于回归。本文将主要介绍用于分类的CART算法的R语言实现。

一、数据读入

数据来自Kaggle的cs-training.csv样本,该样本有15万条的个人消费类贷款数据。 数据下载地址

数据说明:变量名(原始)为文件中变量名,由于原始变量名较长,所以就转换成较短的y、x1、x2…代替。

变量名(原始) 变量名 变量类型 变量描述
id integer 序号
SeriousDlqin2yrs y Y/N 超过90天或更糟的逾期拖欠
RevolvingUtilizationOfUnsecuredLines x1 percentage 无担保放款的循环利用:除了不动产和像车贷那样除以信用额度总和的无分期付款债务的信用卡和个人信用额度总额
age x2 integer 借款人当时的年龄
NumberOfTime30-59DaysPastDueNotWorse x3 integer 35-59天逾期但不糟糕次数
DebtRatio x4 percentage 负债比率
MonthlyIncome x5 real 月收入
NumberOfOpenCreditLinesAndLoans x6 integer 开放式信贷和贷款数量,开放式贷款(分期付款如汽车贷款或抵押贷款)和信贷(如信用卡)的数量
NumberOfTimes90DaysLate x7 integer 90天逾期次数:借款者有90天或更高逾期的次数
NumberRealEstateLoansOrLines x8 integer 不动产贷款或额度数量:抵押贷款和不动产放款包括房屋净值信贷额度
NumberOfTime60-89DaysPastDueNotWorse x9 integer 60-89天逾期但不糟糕次数:借款人在在过去两年内有60-89天逾期还款但不糟糕的次数
NumberOfDependents x10 integer 家属数量:不包括本人在内的家属数量
#读入训练数据集
traindata<-read.csv("cs-training.csv",header = TRUE)
#原始变量名太长,重命名
names(traindata)=c("id","y","x1","x2","x3","x4","x5","x6","x7","x8","x9","x10")
#查看前6行数据,检查变量名是否更新完成
head(traindata)
#将因变量转变为因子格式
traindata$y=as.factor(traindata$y)

得到下面的结果,可以看到,变量名已经更新完成

> head(traindata)
  id y        x1 x2 x3         x4    x5 x6 x7 x8 x9 x10
1  1 1 0.7661266 45  2 0.80298213  9120 13  0  6  0   2
2  2 0 0.9571510 40  0 0.12187620  2600  4  0  0  0   1
3  3 0 0.6581801 38  1 0.08511338  3042  2  1  0  0   0
4  4 0 0.2338098 30  0 0.03604968  3300  5  0  0  0   0
5  5 0 0.9072394 49  1 0.02492570 63588  7  0  1  0   0
6  6 0 0.2131787 74  0 0.37560697  3500  3  0  1  0   1

二、建立训练集和测试集

select<-sample(1:nrow(traindata),length(traindata$id)*0.7) #随机选择70%的行数
train=traindata[select,]#随机选择70%的数据做训练集
test=traindata[-select,]#随机选择30%的数据做训练集

三、建立CART模型

(一)设置前剪枝的条件

tc<-rpart.control(minsplit = 50,minbucket = 20,maxdepth = 30,xval =10,cp = 0.001)
  • minsplit 是最小分支节点数,这里指大于等于50,那么该节点会继续分划下去,否则停止
  • minbucket 叶子节点最小样本数
  • maxdepth 树的深度
  • xval 是交叉验证的次数,xval=10就是10折交叉验证(将数据集分为10组,进行10次拟合,第i次拟合用除了第i组以外的数据训练,用第i组进行预测;目的是减少错误分类。
  • cp 全称为complexity parameter,指某个点的复杂度,对每一步拆分,模型的拟合优度必须提高的程度,用来节省剪枝浪费的不必要的时间

(二)建立决策树

#搭建公式
formular=y~x1+x2+x3+x4+x5+x6+x7+x8+x9+x10
#建设模型,参数为举例说明,具体建模参数可以自行修改
rpart.mod=rpart(formular,data = train,method = "class",
                parms = list(prior=c(0.6,0.4),loss=matrix(c(0,1,2,0),nrow=2),split="gini"),
                control = tc)
  • fomular 回归方程形式: 例如 y~ x 1+ x2+ x3。
  • data 数据: 包含前面方程中变量的数据框( data frame) 。
  • na.action 缺失数据的处理办法: 默认办法是删除因变量缺失的观测而保留自变量缺失的观测。
  • method 根据树末端的数据类型选择相应因变量的分割方法,本参数有四种取值: 连续型>anova; 离散型>class; 计数型( 泊松过程)>poisson; 生存分析型>exp。程序会根据因变量的类型自动选择方法, 但一般情况下最好还是指明本参数, 以便让程序清楚做哪一种树模型。
  • parms 用来设置三个参数:先验概率、损失矩阵、分类纯度的度量方法。anova没有参数;poisson分割有一个参数,先验分布变异系数的比率,默认为1;生存分布的参数和poisson一致;对离散型,可以设置先验分布的分布的概率(prior),损失矩阵(loss),分类纯度(split);
    • priors必须为正值且和为1
    • loss为代价矩阵,必须对角为0且非对角为正数,代价矩阵的行代表实际的分类,列代表预测的分类,在剪枝的时候,叶子节点的加权误差与父节点的误差进行比较,考虑损失矩阵的时候,从将“减少-误差”调整为“减少-损失”
    • split可以是gini(基尼系数)或者information(信息增益);
  • control 控制每个节点上的最小样本量、交叉验证的次数、复杂性参量: 即cp: complexity pamemeter, 这个参数意味着对每一步拆分, 模型的拟合优度必须提高的程度, 等等

(二)后剪枝过程

在分类回归树中可以使用的后剪枝方法有很多,比如:代价复杂度剪枝、最小误差剪枝、悲观误差剪枝等等,这里我们只介绍代价复杂度剪枝法。
rpart包提供了复杂度损失修剪的修剪方法,rpart.mod$cp会告诉分裂到每一层,cp(复杂度)是多少,平均相对误差是多少;交叉验证的估计误差(xerror)、标准误差(xstd)、平均相对误差(xerror±xstd);也可以通过plotcp把cp的折线图打印出来。

> rpart.mod$cp
            CP nsplit rel error    xerror        xstd
1  0.454950358      0 1.0000000 1.0247830 0.009133535
2  0.040251306      1 0.5450496 0.5487305 0.006440166
3  0.019101365      2 0.5047983 0.5085355 0.005126169
4  0.006685254      3 0.4856970 0.4898545 0.004781973
5  0.004512247      4 0.4790117 0.4738762 0.004770271
6  0.003859716     10 0.4484181 0.4541848 0.005548255
7  0.001652621     13 0.4368389 0.4427585 0.005900042
8  0.001419401     15 0.4335337 0.4410733 0.005862466
9  0.001371489     16 0.4321143 0.4391973 0.005865430
10 0.001242517     19 0.4279998 0.4397694 0.005899587
11 0.001201155     21 0.4255148 0.4387756 0.005886477
12 0.001048985     22 0.4243136 0.4368511 0.005834060
13 0.001019105     23 0.4232646 0.4368356 0.005817677
14 0.001000000     24 0.4222455 0.4367234 0.005817659
> plotcp(rpart.mod)

复杂度剪枝法满足的条件是,在交叉验证的估计误差(xerror)尽量小的情况下(不一定是最小值,而是允许最小误差的一个标准差(xstd)之内),选择尽量大的cp值。我们这里选择cp=0.001652621。

> rpart.mod.pru<-prune(rpart.mod,cp=0.001652621)
> rpart.mod.pru$cp
           CP nsplit rel error    xerror        xstd
1 0.454950358      0 1.0000000 1.0247830 0.009133535
2 0.040251306      1 0.5450496 0.5487305 0.006440166
3 0.019101365      2 0.5047983 0.5085355 0.005126169
4 0.006685254      3 0.4856970 0.4898545 0.004781973
5 0.004512247      4 0.4790117 0.4738762 0.004770271
6 0.003859716     10 0.4484181 0.4541848 0.005548255
7 0.001652621     13 0.4368389 0.4427585 0.005900042
8 0.001652621     15 0.4335337 0.4410733 0.005862466

当然,我们也可以选择具有最小xerror的cp的方法,代码如下:

rpart.mod.pru<-prune(rpart.mod,cp=rpart.mod$cptable[which.min(rpart.mod$cptable[,"xerror"])])

四、画出最终的决策树

方法一:使用rpart.plot()

rpart.plot(rpart.mod.pru,branch=1,extra = 102,under = TRUE,faclen = 0,cex = 0.7,main="CART")

方法二:使用plot()和text()

plot(rpart.mod.pru)
text(rpart.mod.pru,all = TRUE,digits = 7,use.n = TRUE,cex=0.9,xpd=TRUE)

方法三:使用draw.tree()

draw.tree(rpart.mod.pru) 

五、模型评估

(一)参数的重要性

> rpart.mod.pru$variable.importance
         x1          x3          x7          x9          x6          x2          x8          x4 
11071.77272  4437.97071  4318.85268  1829.67024   898.98357   227.93847    35.51209    11.18615 

(二)ROC曲线

test.pre<-predict(rpart.mod.pru,test)
plot(roc(test$y,test.pre[,2]), print.auc=TRUE, auc.polygon=TRUE, grid=c(0.1, 0.2),
     grid.col=c("green", "red"), max.auc.polygon=TRUE,
     auc.polygon.col="skyblue", print.thres=TRUE)

(三)混淆矩阵

> test$pre_p<-predict(rpart.mod.pru,test)[,2]
> test$pre=0
> test$pre[which(test$pre_p>0.431)]=1
> confusionMatrix(test$pre,test$y,positive='1')
Confusion Matrix and Statistics

          Reference
Prediction     0     1
         0 32997   703
         1  8953  2347

               Accuracy : 0.7854          
                 95% CI : (0.7816, 0.7892)
    No Information Rate : 0.9322          
    P-Value [Acc > NIR] : 1               

                  Kappa : 0.2467          
 Mcnemar's Test P-Value : <2e-16          

            Sensitivity : 0.76951         
            Specificity : 0.78658         
         Pos Pred Value : 0.20770         
         Neg Pred Value : 0.97914         
             Prevalence : 0.06778         
         Detection Rate : 0.05216         
   Detection Prevalence : 0.25111         
      Balanced Accuracy : 0.77804         

       'Positive' Class : 1     

版权声明:本文为大枫原创文章,转载请注明来源。

坚持原创技术分享,您的支持将鼓励我继续创作!