一、台湾信贷研究目的与问题
1.1 基于聚类算法
基于台湾信贷数据,建立各种聚类模型,根据聚类状况来判断在台湾信贷数据上不同聚类方法的表现。并且在方法论上,探讨每种聚类方法的特点,优势和算法原理,比较和分析每种聚类算法的优缺点和适用情况。 ##1.2 基于分类算法 随机森林、bagging、adaboost 等方法都是基于决策树的组合方法,但是这些 方法和传统的统计思想有很大不同,如果针对具体数据集调整除合适模型来进行预 测是本文的核心,特别是针对信贷数据需要把握的特点即精确度的要求,对这三种 算法进行调试,并比较最终预测结果和这三种算法的优缺点。不论是 boosting 还 是 bagging 当中,当使用的多个分类器的类型都是一致的,如何针对数据集特征挖 掘不同算法和分类器的优势才能选择好的分类器。通过这篇报告,对这三种集成算 法可以有更清晰的了解。 #二、台湾信贷数据集简介及变量说明 本此大数据机器学习实验从UCI机器学习数据集库中选取了经典台湾信贷数据集,并利用该数据来建立目前比较通用聚类模型和集成模型。该鲍鱼数据集是对30000个信贷用户记录个人信息状况、以往信用记录以及银行卡交易状况的描述信息。
信贷数据将这30000条信贷用户记录分为两类:下一月份违约的用“1”标识。以及下一月份未违约的用“0”标识。该数据集的属性信息以及变量描述如表1-1所示,表中给定的是变量名称,变量说明,变量类型和取值范围等。
\(~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\)表1-1 属性变量说明表
变量名 | 变量说明 | 变量类型 | 取值范围 |
---|---|---|---|
X1 | 给定额度 | 数值型 | 1万-100万 |
X2 | 性别 | 分类型 | 1:男,2:女 |
X3 | 教育水平 | 分类型 | 1:graduate;2:university;3:high school;4:others |
X4 | 婚姻状况 | 分类型 | 1:married;2:single;3:others |
X5 | 年龄 | 数值型 | 21-79 |
X6-X11 | 还款状态 | 数值型 | <0:按时还款,>0:超期相应月数还款 |
X12-X17 | 票据金额 | 数值型 | X12表示2015-09,以此类推 |
X18-X23 | 先前付款额 | 数值型 | X18表示2015-09,以此类推 |
Y | 是否违约 | 分类型 | 0:未违约,1:违约 |
三、聚类算法与分类算法工具包载入
载入与本次试验相关的数据处理包’reshape2’,‘dplyr’,‘pryr’等,绘图包’ggplot2’,‘DiagrammeR’等,机器学习包’caret’,’xgboost’等以及性能测试包’pryr’等。由于本次试验需要对比各种机器学习算法的ROC曲线以及AUC值,所以进行了pROC的调用。
#首先需要进行xgboost包的安装,只需在R中运行install.packages(‘xgboost’)即可。
library(xgboost) #导入极限梯度下降法包
library(caret)
library(ggplot2) #绘图包
library(DiagrammeR)
library(reshape2) #数据处理包
library(dplyr)
library(pryr)
library(pROC) #ROC曲线包
library(plyr)
library(showtext) #使作图的字体更加丰富
library(RColorBrewer) #增加调色板
library(randomForest) #加载随机森林包
library(pryr) #加载性能测试包
library(adabag) #加载GBDT梯度提升树包
library(xgboost) #加载XGBoost提升树包
library(DiagrammeR)
library(reshape2)
library(dbscan)
library(fpc)
library(sparcl)
四、台湾信贷数据可视化分析
4.1信贷数据预处理
#数据预处理
#数据说明
taiwan<- read.csv("D:/bigdatahw/算法/作业/card1.csv",head=TRUE,sep=',') #读取台湾信用数据
taiwan$SEX<-as.factor(taiwan$SEX)
taiwan$EDUCATION<-as.factor(taiwan$EDUCATION)
taiwan$MARRIAGE<-as.factor(taiwan$MARRIAGE)
names(taiwan)[25]="default" #重命名因变量
taiwan$default<-as.factor(taiwan$default)
levels(taiwan$SEX)=list(M="1",F="2") #进行重命名等级
levels(taiwan$EDUCATION)=list(others="0",graduate="1",university="2", highschool="3",others="4",others="5",others="6")
levels(taiwan$MARRIAGE)=list(married="1", single="2",others="3",others="0")
levels(taiwan$default)=list(T="1", F="0")
4.2信贷数据描述性分析
4.2.1教育状况与违约占比性别分面风玫瑰图
从图中可以看出,不管是男性还是女性,信贷用户中大学毕业生人数比较多,其次是研究生。其他学历人数较少,还可以看出男性的信贷违约人数要少于女性,说明女性更容易违约。在途中还可以看出随着学历的逐渐上升,违约状况也有所改观,说明教育水平会提升信用状况。
label<-c("others","highschool","university","graduate")
taiwan$EDUCATION<- ordered(taiwan$EDUCATION, levels = label)
ggplot(taiwan,aes(x=default,fill=EDUCATION))+
geom_bar()+coord_polar(theta = 'x')+
scale_fill_brewer(palette='Spectral')+facet_wrap(~SEX)+theme_bw()+
labs(x="违约状况",y="频数",fill="学历状况",title='分面风玫瑰图')+
scale_x_discrete()+coord_polar(theta="x")+
theme(plot.title = element_text(hjust =
0.5,family="myFont",size=18,color="gold3"),
panel.background=element_rect(fill='aliceblue'))
4.2.2违约与年龄分布直方图
根据所受教育水平的不同,违约状况的的年龄分布也有所不同,在学历为其他的用户中违约的年龄分布比较均匀,在高中毕业的水平下,总体的年龄分布比较均匀,违约人的年龄分布也是比较均匀的,在大学的教育水平下,年龄分布比较不均匀,整体成右偏分布,而违约人的年龄分布峰较低,比较平缓。在研究生阶段的的年龄分布峰较高,成尖峰分布,且有右偏拖尾。整体的违约比率较低,分布比较平缓。
label<-c("F","T")
taiwan$default<- ordered(taiwan$default, levels = label)
p<-ggplot(taiwan,aes(x=AGE,fill=default))
p+geom_histogram(position="identity",alpha=0.5)+
ggtitle('各学历违约状况与年龄分布直方图')+
theme(plot.title = element_text(hjust =
0.5,family="myFont",size=18,color="red"),
panel.background=element_rect(fill='aliceblue')) +
xlab("年龄") +ylab("频数")+
facet_wrap(~EDUCATION)
4.2.3银行给定额度与违约箱线图
如图所示,白色的点代表着中位数,而象限图中的白线则代表着均值。对于给定的信用额度与违约的关系上来看,可以看出的关系是,对于未来不违约的人通常银行给予的信用额度是比较高的,说明银行在当时信用分配筛选时,是下过一番功夫的。因此会导致未来违约的人的信用额度偏低。
ggplot(taiwan,aes(x=default,y=LIMIT_BAL,fill=default))+
geom_boxplot(outlier.size=1.5, outlier.shape=15,notch=TRUE,alpha=.35)+
stat_summary (fun.y="mean",geom="point",shape=23,size=2,fill="white")+
xlab("违约与否") + ylab("给定的信用额度")+
ggtitle('给定信用额度与违约箱线图')+ylim(0,550000)+
theme(plot.title = element_text(hjust = 0.5,
family="myFont",size=18,color="red"),
panel.background=element_rect(fill='aliceblue',color='black'))
4.2.4婚姻状况与违约之间关系
在图中可以看出婚姻状况与违约之间的关系,数量关系没有描述统计的必要,主要进行百分比之间的转化,在分面饼状图中可以清楚的看出,婚姻状况对违约并没有很大的影响,主要的影响是比较细微的,单身的违约概率是比较小的,大约占到总体的1/5左右,而已婚和其他的状况违约概率是几乎一样的,都占各自总体的1/4左右。
ggplot(taiwan,aes(x=factor(1),fill=default))+
geom_bar(aes(fill=default),position="fill")+
coord_polar(theta="y")+
ggtitle('婚姻状况与违约之间关系')+
theme(plot.title = element_text(hjust =
0.5,family="myFont",size=18,color="black"),
panel.background=element_rect(fill='aliceblue',color='black'))+
facet_wrap(~MARRIAGE)
4.2.5教育与违约关系
在教育水平与违约状况环形图中,也可以看到,违约占比较高的教育水平为高中阶段,其次是大学,然后是研究生,相比之下,其他的教育水平违约占比较低,因此我们也可以大胆的推断other是一种更高的教育水平。有可能是博士阶段。各个学历水平的违约率都没超过1/4,other更是小于1/10。
ggplot(taiwan, aes(EDUCATION))+geom_bar(aes(fill=default),position="fill")+
coord_polar(theta = "y")+ggtitle('教育水平与违约之间关系')+
theme(plot.title = element_text(hjust =
0.5,family="myFont",size=18,color="black"),
panel.background=element_rect(fill='aliceblue',color='black'))
4.2.6年龄与给定额度关系
我们筛选的是具有违约状况的信用记录来进行分析。由于点的数量太多,因此绘制了分箱密度估计图,横坐标是违约用户的年龄,纵坐标是给定额度的对数值。来分析对于违约的用户,什么样的年龄和给定额度下违约的人数较多,可以在图中看到,红色区域对应着25岁给定额度为10的人数违约较多,其次还有25岁给定额度为11左右的人。因此银行在分配额度是应该注意这一点,利用密度图来规避风险,尽量少分配给25年龄段更多的信用。还可以看出给定额度与年龄的关系并不大,年龄小一样可以获得较高额度。
taiwan<-taiwan[which(taiwan$default=='T'),]
p=ggplot(taiwan,aes(x=AGE,y=log(LIMIT_BAL)))
#默认等高线图进行分箱化处理
p+geom_point(alpha=0.2)+stat_bin2d()+
scale_fill_gradient(low="lightblue",high="red")+stat_density2d()+
theme(plot.title = element_text(hjust =
0.5,family="myFont",size=18,color="slateblue2"),
panel.background=element_rect(fill='papayawhip'))+
labs(x='年龄',y='log(给定额度)',title='年龄与给定额度密度关系')
五、基于台湾信贷数据的聚类方法比较与分析
5.1 数据预处理
setwd('D:/bigdatahw/算法/作业') #设置工作路径
taiwan=read.csv("card1.csv")
names(taiwan)[25]="default" #重命名因变量
#特征变量性别、年龄、教育程度以及下月是否违约转换为因子变量
taiwan$default<- as.factor(taiwan$default)
taiwan$SEX <- as.factor(taiwan$SEX)
taiwan$EDUCATION <- as.factor(taiwan$EDUCATION)
taiwan$MARRIAGE <- as.factor(taiwan$MARRIAGE)
summary(taiwan)
## ID LIMIT_BAL SEX EDUCATION MARRIAGE
## Min. : 1 Min. : 10000 1:11888 0: 14 0: 54
## 1st Qu.: 7501 1st Qu.: 50000 2:18112 1:10585 1:13659
## Median :15000 Median : 140000 2:14030 2:15964
## Mean :15000 Mean : 167484 3: 4917 3: 323
## 3rd Qu.:22500 3rd Qu.: 240000 4: 123
## Max. :30000 Max. :1000000 5: 280
## 6: 51
## AGE PAY_0 PAY_2 PAY_3
## Min. :21.00 Min. :-2.0000 Min. :-2.0000 Min. :-2.0000
## 1st Qu.:28.00 1st Qu.:-1.0000 1st Qu.:-1.0000 1st Qu.:-1.0000
## Median :34.00 Median : 0.0000 Median : 0.0000 Median : 0.0000
## Mean :35.49 Mean :-0.0167 Mean :-0.1338 Mean :-0.1662
## 3rd Qu.:41.00 3rd Qu.: 0.0000 3rd Qu.: 0.0000 3rd Qu.: 0.0000
## Max. :79.00 Max. : 8.0000 Max. : 8.0000 Max. : 8.0000
##
## PAY_4 PAY_5 PAY_6 BILL_AMT1
## Min. :-2.0000 Min. :-2.0000 Min. :-2.0000 Min. :-165580
## 1st Qu.:-1.0000 1st Qu.:-1.0000 1st Qu.:-1.0000 1st Qu.: 3559
## Median : 0.0000 Median : 0.0000 Median : 0.0000 Median : 22382
## Mean :-0.2207 Mean :-0.2662 Mean :-0.2911 Mean : 51223
## 3rd Qu.: 0.0000 3rd Qu.: 0.0000 3rd Qu.: 0.0000 3rd Qu.: 67091
## Max. : 8.0000 Max. : 8.0000 Max. : 8.0000 Max. : 964511
##
## BILL_AMT2 BILL_AMT3 BILL_AMT4 BILL_AMT5
## Min. :-69777 Min. :-157264 Min. :-170000 Min. :-81334
## 1st Qu.: 2985 1st Qu.: 2666 1st Qu.: 2327 1st Qu.: 1763
## Median : 21200 Median : 20089 Median : 19052 Median : 18105
## Mean : 49179 Mean : 47013 Mean : 43263 Mean : 40311
## 3rd Qu.: 64006 3rd Qu.: 60165 3rd Qu.: 54506 3rd Qu.: 50191
## Max. :983931 Max. :1664089 Max. : 891586 Max. :927171
##
## BILL_AMT6 PAY_AMT1 PAY_AMT2 PAY_AMT3
## Min. :-339603 Min. : 0 Min. : 0 Min. : 0
## 1st Qu.: 1256 1st Qu.: 1000 1st Qu.: 833 1st Qu.: 390
## Median : 17071 Median : 2100 Median : 2009 Median : 1800
## Mean : 38872 Mean : 5664 Mean : 5921 Mean : 5226
## 3rd Qu.: 49198 3rd Qu.: 5006 3rd Qu.: 5000 3rd Qu.: 4505
## Max. : 961664 Max. :873552 Max. :1684259 Max. :896040
##
## PAY_AMT4 PAY_AMT5 PAY_AMT6 default
## Min. : 0 Min. : 0.0 Min. : 0.0 0:23364
## 1st Qu.: 296 1st Qu.: 252.5 1st Qu.: 117.8 1: 6636
## Median : 1500 Median : 1500.0 Median : 1500.0
## Mean : 4826 Mean : 4799.4 Mean : 5215.5
## 3rd Qu.: 4013 3rd Qu.: 4031.5 3rd Qu.: 4000.0
## Max. :621000 Max. :426529.0 Max. :528666.0
##
## 定义标准化函数,将原始数据压缩到0-1之间,同一量纲
myfun=function(x)
{
m1=max(x)
m2=min(x)
y=(x-m1)/(m2-m1)
return(y)
}
## 抽取部分样本作为建模数据,并进行标准化处理
set.seed(123)
s=sample(1:dim(taiwan)[1],500)
taiwan_num=apply(taiwan[s,c(2,6:24)],2,myfun) #聚类数值数据
taiwan_char_num=cbind(taiwan_num,taiwan[s,3:5]) #聚类数值+分类数据
5.2AGNES算法层次聚类
## 由于聚类分析是无监督分类,无法知道聚类结果到底是属于哪一类。
## 所以要定义函数变换混淆矩阵,使得对角线上的元素最大,然后输
## 出混淆矩阵,以便确定聚类结果分别属于哪一个类。定义函数找出
## 对角线上数量最大的矩阵
myfun1=function(a,b)
{
table<-table(a, b)
Accuracy1=table[1,1]+table[2,2]
Accuracy2=table[1,2]+table[2,1]
if(Accuracy1>Accuracy2){
confusion<-table(a,b)
rownames(confusion)<-c('未违约','违约')
colnames(confusion)<-c('未违约','违约')
return(confusion)}
else{ label<-c("2","1")
b<- ordered(b, levels = label)
confusion<-table(a,b)
rownames(confusion)<-c('未违约','违约')
colnames(confusion)<-c('未违约','违约')
return(confusion)}
}
d<-dist(taiwan_num) #计算样本之间的欧式距离
hc<-hclust(d, method="complete") #根据距离进行聚类,类间距离定义为全连接
plot(hc) #显示聚类结果图
hccut<-cutree(hc,k=2) #将类别数定为2
myfun1(taiwan[s,]$default, hccut) #需要变0-1
## b
## a 未违约 违约
## 未违约 381 1
## 违约 118 0
5.3Kmeans聚类
kc<-kmeans(taiwan_num,2) #k均值聚类将样本聚成2类
myfun1(taiwan[s,]$default, kc$cluster)
## b
## a 未违约 违约
## 未违约 271 111
## 违约 58 60
#显示混淆矩阵,可以调整以下顺序就会不同了,遍历一下
5.4DBSCAN基于密度聚类
##确定最优eps
kNNdistplot(taiwan_num,k=2)
abline(h=0.3)
#可达距离eps设置为0.45,最小可达数为50,也就是说核心点的最小可达点最少要50个
ds=dbscan(taiwan_num,eps=0.1,MinPts=500,
scale=TRUE,showplot=TRUE,method="raw") #显示聚类图谱图
ds #显示聚类结果
## dbscan Pts=500 MinPts=500 eps=0.1
##
## 0
## 500
table(taiwan[s,]$default, ds$cluster)
##
## 0
## 0 382
## 1 118
#optics算法,载入dbscan层次聚类包,采用的算法为optics,eps可达距离为1。
#ε邻域大小的上限。限制邻域大小可以提高性能,而且只要设置得不太低,就
#不会对排序产生什么影响。稀疏K均值聚类
opt<-optics(d, eps=1, minPts=4)
plot(opt) #可达距离图
5.5稀疏聚类
5.5.1Kmeans稀疏聚类
perm <- KMeansSparseCluster.permute(taiwan_num,K=2,wbounds=seq(1.5,7.5,0.5),nperms=3)#选择最优的tunings
## 101234201234301234015016017018019011001110112011301
## Permutation 1 of 3
## 10122013014015016017018019011001110112011301
## Permutation 2 of 3
## 10122013014015016017018019011001110112011301
## Permutation 3 of 3
## 10122013014015016017018019011001110112011301
print(perm)
## Tuning parameter selection results for Sparse K-means Clustering:
## Wbound # Non-Zero W's Gap Statistic Standard Deviation
## 1 1.5 6 -0.6080 0
## 2 2.0 6 -0.4944 0
## 3 2.5 12 -0.4264 0
## 4 3.0 20 -0.4047 0
## 5 3.5 20 -0.4047 0
## 6 4.0 20 -0.4047 0
## 7 4.5 20 -0.4047 0
## 8 5.0 20 -0.4047 0
## 9 5.5 20 -0.4047 0
## 10 6.0 20 -0.4047 0
## 11 6.5 20 -0.4047 0
## 12 7.0 20 -0.4047 0
## 13 7.5 20 -0.4047 0
## Tuning parameter that leads to largest Gap statistic: 3
km<- KMeansSparseCluster(taiwan_num,K=2,wbounds=perm$bestw)#在最优的tuning下求解最优权重,并聚类
## 0123
print(km)
## Wbound is 3 :
## Number of non-zero weights: 20
## Sum of weights: 2.996815
## Clustering: 1 2 1 2 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 1 1 2 1 1 2 2 1
## 2 1 1 1 1 2 1 1 2 1 1 1 1 1 1 1 1 2 2 1 1 1 1 1 2 2 2 1 1 1 1 2 2 2 2 1 1
## 1 1 2 2 1 2 2 1 2 1 2 1 1 2 1 2 2 2 2 1 2 1 1 1 2 1 1 2 2 2 1 2 1 2 2 1 1
## 1 1 1 2 1 2 1 1 1 1 1 1 1 1 2 2 1 1 1 1 1 1 2 2 1 1 1 2 2 1 1 2 2 1 2 1 1
## 1 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 2 1 1 2 1 1 1 1 1 1 1 1 2 2 1 1 1 2 1 1
## 1 1 2 1 1 2 2 1 1 2 1 1 1 1 1 2 2 1 2 1 1 1 1 2 1 2 2 1 1 2 2 1 1 1 1 2 1
## 2 2 1 1 2 2 1 1 1 2 2 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 2 1 1 1 2 1 2 1 1 1 1
## 1 1 1 1 1 1 1 1 1 1 1 1 1 2 1 1 2 2 1 1 1 1 1 1 1 2 1 2 1 2 1 1 1 1 1 2 1
## 2 1 2 2 1 1 2 1 1 2 1 1 1 1 1 1 1 1 1 2 2 2 1 2 1 2 1 1 2 1 1 2 1 1 1 1 1
## 2 2 1 1 2 1 1 1 1 1 1 1 1 1 1 2 2 2 1 1 1 1 1 1 2 2 2 1 1 2 2 1 1 1 2 1 1
## 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 2 2 2 1 1
## 1 1 1 2 1 1 2 1 1 1 1 2 1 1 1 1 1 2 2 2 1 2 1 1 2 1 2 1 1 1 2 1 1 2 2 1 1
## 1 1 1 1 1 1 2 2 1 1 1 2 2 1 2 1 2 1 2 2 2 2 1 1 1 1 2 1 2 1 1 1 1 2 1 2 1
## 1 1 1 1 1 1 1 1 2 1 1 2 2 2 2 2 1 1 1 1 1 1 1 2 1
barplot(km[[1]][[1]])#可以看到哪些特征非零
myfun1(taiwan[s,]$default, km[[1]][[2]])
## b
## a 未违约 违约
## 未违约 259 123
## 违约 86 32
5.5.2层次稀疏聚类
#稀疏层次聚类的调优参数选择
perm.out <- HierarchicalSparseCluster.permute(as.matrix(taiwan_num), wbounds=c(1.5,2:6),nperms=10)
## Running sparse hierarchical clustering on unpermuted data
## 123456
## Running sparse hierarchical clustering on permuted data
## Permutation 1 of 10
## 123456
## Permutation 2 of 10
## 123456
## Permutation 3 of 10
## 123456
## Permutation 4 of 10
## 123456
## Permutation 5 of 10
## 123456
## Permutation 6 of 10
## 123456
## Permutation 7 of 10
## 123456
## Permutation 8 of 10
## 123456
## Permutation 9 of 10
## 123456
## Permutation 10 of 10
## 123456
print(perm.out)
## Tuning parameter selection results for Sparse Hierarchical Clustering:
## Wbound # Non-Zero W's Gap Statistic Standard Deviation
## 1 1.5 5 0.0164 5e-04
## 2 2.0 7 0.0564 5e-04
## 3 3.0 14 0.1203 4e-04
## 4 4.0 20 0.1479 4e-04
## 5 5.0 20 0.1479 4e-04
## 6 6.0 20 0.1479 4e-04
## Tuning parameter that leads to largest Gap statistic: 4
plot(perm.out)
# 执行稀疏层次聚类
sparsehc <- HierarchicalSparseCluster(dists=perm.out$dists,
wbound=perm.out$bestw, method="complete")
## 12345678910
par(mfrow=c(1,2))
plot(sparsehc)
plot(sparsehc$hc)
print(sparsehc)
## Wbound is 4 :
## Number of non-zero weights: 20
## Sum of weights: 3.81629
cutree(sparsehc$hc,2)
## 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
## 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2
## 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
## 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 1 1
## 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
## 1 1 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1
## 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
## 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
## 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
## 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
## 1 1 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1
## 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
## 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 2 1 1
## 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
## 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
## 1 1 1 1 2 1 1 1 1 1 1 1 1 2 1 1 1 1
## 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
## 1 1 1 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1
## 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
## 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
## 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
## 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
## 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1
## 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
## 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306
## 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324
## 2 1 1 1 1 1 1 1 1 1 2 1 1 1 1 1 2 2
## 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342
## 1 1 2 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1
## 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360
## 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378
## 1 1 2 1 1 1 1 1 1 1 1 2 1 1 1 1 2 1
## 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396
## 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2
## 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414
## 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432
## 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450
## 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468
## 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486
## 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1
## 487 488 489 490 491 492 493 494 495 496 497 498 499 500
## 1 1 1 1 1 1 1 1 1 1 1 1 1 1
myfun1(taiwan[s,]$default,cutree(sparsehc$hc,2))
## b
## a 未违约 违约
## 未违约 366 16
## 违约 111 7
# 使用类标签知识来比较真实类
#获得聚类的标签
par(mfrow=c(1,1))
y = cutree(hc, 3)
ColorDendrogram(hc,y=y,main="My Simulated Data",branchlength=.007)
#现在,如果我们想看看数据是否包含了一个*二次聚类,
#在计算第一个得到的数据之后。我们寻找互补稀疏聚类:
# 重做分析,但这次使用“绝对值”不同:
perm.out <- HierarchicalSparseCluster.permute(as.matrix(taiwan_num),
wbounds=c(1.5,2:6),
nperms=5,
dissimilarity="absolute.value")
## Running sparse hierarchical clustering on unpermuted data
## 123456
## Running sparse hierarchical clustering on permuted data
## Permutation 1 of 5
## 123456
## Permutation 2 of 5
## 123456
## Permutation 3 of 5
## 123456
## Permutation 4 of 5
## 123456
## Permutation 5 of 5
## 123456
print(perm.out)
## Tuning parameter selection results for Sparse Hierarchical Clustering:
## Wbound # Non-Zero W's Gap Statistic Standard Deviation
## 1 1.5 3 0.0037 2e-04
## 2 2.0 9 0.0138 1e-04
## 3 3.0 13 0.0420 1e-04
## 4 4.0 20 0.0677 1e-04
## 5 5.0 20 0.0677 1e-04
## 6 6.0 20 0.0677 1e-04
## Tuning parameter that leads to largest Gap statistic: 4
plot(perm.out)
# 执行稀疏层次聚类
sparsehc <- HierarchicalSparseCluster(dists=perm.out$dists, wbound=perm.out$bestw, method="complete", dissimilarity="absolute.value")
## 123456
par(mfrow=c(1,2))
plot(sparsehc)
5.6双向聚类
5.6.1数据预处理
##双向聚类
##数据预处理,将分类变量处理成独热编码
library(caret)
taiwan=read.csv("card1.csv")
ohe_feats = c('SEX', 'EDUCATION', 'MARRIAGE')
taiwan$SEX<-as.factor(taiwan$SEX)
taiwan$EDUCATION<-as.factor(taiwan$EDUCATION)
taiwan$MARRIAGE<-as.factor(taiwan$MARRIAGE)
dummies <- dummyVars(~ SEX + EDUCATION + MARRIAGE, data = taiwan)
df_all_ohe <- as.data.frame(predict(dummies, newdata = taiwan))
taiwan_bi <- cbind(df_all_ohe,taiwan_num)
5.6.2双向聚类分析
library(biclust)
taiwan_bi=as.matrix(taiwan_bi[s,])
heatmap(taiwan_bi)
bidata=binarize(taiwan_bi) #处理成二分数据
## [1] "Threshold: 0.5"
bic<-biclust(bidata,method=BCBimax(),minr=400, minc=3)
bic #以BIMAX方法进行聚类
##
## An object of class Biclust
##
## call:
## biclust(x = bidata, method = BCBimax(), minr = 400, minc = 3)
##
## Number of Clusters found: 100
##
## First 5 Cluster sizes:
## BC 1 BC 2 BC 3 BC 4 BC 5
## Number of Rows: 498 498 497 496 495
## Number of Columns: 3 3 4 4 5
heatmapBC(x = bidata,
bicResult = bic,main="BIMAX算法双向聚类热力图")
## [1] "yto 497"
## [1] "xlo 2"
## [1] "yto 0"
## [1] "xlo 1"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 1"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 1"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 2"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 1"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 1"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
## [1] "yto 0"
## [1] "xlo 0"
bic1<-biclust(bidata,method=BCCC(), number=2)
bic1 #以CC方法进行聚类
##
## An object of class Biclust
##
## call:
## biclust(x = bidata, method = BCCC(), number = 2)
##
## There was one cluster found with
## 500 Rows and 33 columns
##heatmapBC(bidata,bic1,main="CC算法双向聚类热力图") #做出热力图
5.7聚类算法对比
在第五章中,基于台湾信贷数据进行了不同方式的聚类。不同的聚类方式对类别间的差异程度的衡量有所不同,层次聚类和k均值聚类是根据点与点之间的距离进行聚类的,衡量距离的定义有很多,本章中采用的都是欧氏距离。而Dbscan聚类是基于密度的,将密度大的区域作为一个类,而将密度小的区域作为类与类的边界。
在基于距离的聚类中,AGNES层次聚类是一种自下而上的一种层次能聚方法,不断地将点通过相似的距离进行融合,而k均值聚类则是通过给定的k个类,不断迭代,使规划目标类间距离最小,从而找到核心点,确定类别。
而基于密度聚类的Dbscan聚类相较于基于距离聚类的优势就是可以做出任何形式的类,而不需要提前给出类的个数K的个数。缺点就单纯的依靠点与点之间的密度进行距离,衡量的是某一块区域之内的点的个数,缺乏现实意义,聚类比较盲目,也可以再基于台湾的信贷数据上看到,的确其准确度较低。
对于层次和k均值聚类,使用的都是数据的全部特征,这样做不但会增加计算量是计算效率降低,还会使得聚类效果不明显,忽略一些重要的变量,稀疏聚类的优势就是通过增加W权重,并对权重进行范数为1的限制,来对每一个特征指标在聚类中的表现进行限制。会突出一别变量的作用,在特征变量较多的状况的基因数据下,表现较好。起到数据压缩的效果。
双向聚类则是对观测和指标都进行聚类,以这种方式来反映一些变量在某些指标下的相似状况,而非全部特征下,因为能在全部指标下某些观测是不具有相似性的,所以更加具有实际意义。且尚香聚类的BIMAX在处理系数矩阵时具有独特的优势,在储存空间和运算时间上都较少。CC算法对BIMX的改进再在于,它弥补了在观测和指标较多是进行单列,但行的单节点删除的BIMAX法的运行效率较低,采用了大规模的多节点删除算法和节点添加算法,在大数据量下的表现会更加好。运行时间会进一步缩短。 最后,基于台湾信贷数据的聚类运算结果表如下表所示:
\(~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\)表1-2 信贷数据聚类算法比较表
准确率 | 运行时间(s) | |
---|---|---|
层次聚类 | 76.2% | 0.25 |
k-means聚类 | 66.2% | 0.85 |
dbcan密度聚类 | 76.4% | 0.67 |
k-means稀疏聚类 | 58.2% | 0.94 |
层次稀疏聚类 | 74.6% | 0.45 |
从对比表来看,基于台湾信贷数据上来看,在准确率上密度聚类的效果最好,而从运行时间上来看,层次聚类由于计算复杂小,所以耗费时间最短。
六、基于台湾信贷数据的分类算法的比较与分析
6.1 随机森林算法
随机森林是一种很灵活实用的方法,它有如下几个特点:
- 在当前所有算法中,具有极好的准确率
- 能够有效地运行在大数据集上
- 能够处理具有高维特征的输入样本,而且不需要降维
- 能够评估各个特征在分类问题上的重要性
- 在生成过程中,能够获取到内部生成误差的一种无偏估计
- 对于缺省值问题也能够获得很好得结果
6.1.1 随机森林数据预处理
#数据预处理
alldata <- read.csv("D:/bigdatahw/算法/作业/card1.csv",head=TRUE,sep=',')
alldata$default.payment.next.month <- as.factor(alldata$default.payment.next.month)
alldata$SEX <- as.factor(alldata$SEX)
alldata$EDUCATION <- as.factor(alldata$EDUCATION)
alldata$MARRIAGE <- as.factor(alldata$MARRIAGE)
alldata$PAY_0 <- as.factor(alldata$PAY_0)
alldata$PAY_2 <- as.factor(alldata$PAY_2)
alldata$PAY_3 <- as.factor(alldata$PAY_3)
alldata$PAY_4 <- as.factor(alldata$PAY_4)
alldata$PAY_5 <- as.factor(alldata$PAY_5)
alldata$PAY_6 <- as.factor(alldata$PAY_6)
#切分训练集和测试集
n <- sample(1:nrow(alldata),0.8*nrow(alldata))
train <- alldata[n,-1]
test <- alldata[-n,-1]
6.1.2 随机森林实证检验
rf <- randomForest(default.payment.next.month~.,data = train,
mtry=9,ntree=200,importance = T)
#查看训练集错误率随树的数量变化情况
plot(rf)
#查看训练集平均错误率
mean(rf$err.rate)
## [1] 0.29328
#训练集的混淆矩阵
rf$confusion
## 0 1 class.error
## 0 17563 1126 0.06024934
## 1 3271 2040 0.61589155
#变量重要性
imp <- importance(x=rf)
imp
## 0 1 MeanDecreaseAccuracy MeanDecreaseGini
## LIMIT_BAL 17.2029543 9.7047482 21.266565 475.47075
## SEX 0.5943296 1.7876208 1.380573 69.81759
## EDUCATION 4.3848673 -0.8927275 3.416634 155.05200
## MARRIAGE 8.5000092 -2.0870822 6.802100 81.16270
## AGE 16.7357291 2.1579620 15.888386 558.61180
## PAY_0 68.6409536 20.7379376 89.123802 980.54191
## PAY_2 24.3634091 -1.5713306 24.749841 387.41056
## PAY_3 22.3145536 -0.6133761 23.650806 224.12159
## PAY_4 25.7885982 -3.9628031 26.276405 137.14523
## PAY_5 18.7097157 4.9360715 22.120779 124.00833
## PAY_6 20.9214964 9.3434181 26.775247 116.52891
## BILL_AMT1 18.8808991 11.8397139 24.933455 519.15213
## BILL_AMT2 29.6618252 -6.7161920 32.357146 434.70636
## BILL_AMT3 27.7400577 -4.9780282 30.980817 400.06105
## BILL_AMT4 31.3560986 -8.6779579 34.183192 392.65935
## BILL_AMT5 25.4924452 -0.2068033 30.243083 390.36588
## BILL_AMT6 23.8797758 1.5465705 29.403866 402.75028
## PAY_AMT1 20.7704798 -4.2723432 22.589126 419.08704
## PAY_AMT2 19.5958596 2.8907808 22.421400 398.55678
## PAY_AMT3 21.8057086 6.1405462 26.279318 386.16816
## PAY_AMT4 17.6185767 5.4049239 22.768492 365.50157
## PAY_AMT5 22.1770788 0.2160371 26.252567 370.52992
## PAY_AMT6 25.1897353 4.5908928 26.634603 398.01621
varImpPlot(rf)
#运行时间和消耗内存
#timecost <- system.time(randomForest(default.payment.next.month~.,
#data = train,
#mtry=9,ntree=500,
#importance = T))
#print(timecost)
#定义评价函数
index2=function(table) {
Accuracy=table[1,1]+table[2,2]
#真阳性率+真阴性率=预测准确率
precision=table[2,2]/sum(table[,2])
#预测阳性率=精确度
recall=table[2,2]/sum(table[2,])
#第二类错误,灵敏度 =召回率
F_measure=2*precision*recall/(precision+recall)
#对前两者进行加权,综合结果
results=data.frame(Accuracy=Accuracy,
recall=recall,
precision=precision,
F_measure=F_measure)
return(results)
}
#测试集进行检验
pred1 <- predict(rf,test[,-25])
#测试集混淆矩阵
table(pred1,test$default.payment.next.month)
##
## pred1 0 1
## 0 4387 827
## 1 288 498
#测试集评价
rf.pred= predict(rf,newdata=test[,-25])
rf.real=test$default.payment.next.month
table_RF=table(rf.real,rf.pred)/nrow(test)
a=index2(table_RF)
print(a)
## Accuracy recall precision F_measure
## 1 0.8146667 0.3766038 0.6356688 0.4729858
#ROC曲线
library(ROCR)
re.pred= predict(rf,newdata=test[,-25],type = "prob")
rocr = prediction(as.vector(re.pred[,2]),
test$default.payment.next.month)
AUC = performance(rocr,"auc")
print(AUC@y.values[[1]])
## [1] 0.7620552
ROC = performance(rocr,"tpr","fpr")
plot(ROC,main="ROC plot")
text(0.5,0.5,paste("AUC = ",
format(AUC@y.values[[1]],
digits=5,
scientific=FALSE)))
6.2 Adaboost集成算法
AdaBoost 采取加权多数表决的方法。 具体地,加大分类误差率小的弱分类器的权值,使其在表决中起较大的作用,减小 分类误差率大的弱分类器的权值,使其在表决中起较小的作用。
6.2.1 Adaboost数据预处理
credit <- read.csv("D:/bigdatahw/算法/作业/card1.csv",head=TRUE,sep=',')
credit<-credit[,-1] #去除id行
names(credit)[24] <- 'label'
credit$label <- as.factor(credit$label)
credit$SEX <- as.factor(credit$SEX)
credit$EDUCATION <- as.factor(credit$EDUCATION)
credit$MARRIAGE <- as.factor(credit$MARRIAGE)
credit$PAY_0 <- as.factor(credit$PAY_0)
credit$PAY_2 <- as.factor(credit$PAY_2)
credit$PAY_3 <- as.factor(credit$PAY_3)
credit$PAY_4 <- as.factor(credit$PAY_4)
credit$PAY_5 <- as.factor(credit$PAY_5)
credit$PAY_6 <- as.factor(credit$PAY_6)
#按标签比例各20%筛选训练集与测试集
idx0 <- which(credit$label == 1)
idx1 <- which(credit$label == 0)
cls0 <- sample(idx0,round(0.2 * length(idx0)))
cls1 <- sample(idx1,round(0.2 * length(idx1)))
tst <- credit[c(cls0,cls1),]
trn <- credit[-c(cls0,cls1),]
#查看各数据矩阵维度
dim(credit)
## [1] 30000 24
dim(tst)
## [1] 6000 24
dim(trn)
## [1] 24000 24
6.2.2 Adaboost实证检验
now <- Sys.time()
mem_change(model.AdaBoost <- boosting(label~.,data = trn))
## 48.4 MB
Sys.time() - now
## Time difference of 6.846082 mins
model.pred <- predict(model.AdaBoost,newdata = tst,type='class')
model.pred$confusion #查看混淆矩阵
## Observed Class
## Predicted Class 0 1
## 0 4454 844
## 1 219 483
cal=function(table) {
Accuracy=table[1,1]+table[2,2]
#真阳性率+真阴性率=预测准确率
precision=table[2,2]/sum(table[,2])
#预测阳性率=精确度
recall=table[2,2]/sum(table[2,])
#第二类错误,灵敏度 =召回率
F_measure=2*precision*recall/(precision+recall)
#对前两者进行加权,综合结果
results=data.frame(Accuracy=Accuracy,recall=recall,precision=precision,F_measure=F_measure)
return(results)
}
cal(model.pred$confusion / 6000)
## Accuracy recall precision F_measure
## 1 0.8228333 0.6880342 0.3639789 0.4760966
6.3 XGBoost集成算法
XGBoost 算法总结起来大致其有三个优点:高效、准确度、模型的交互性:
正则化:标准 GBDT 提升树算法的实现没有像 XGBoost 这样的正则化 步骤。正则化用于控制模型的复杂度,对减少过拟合也是有帮助的。XGBoost 也正是以“正则化提升”技术而闻名。
并行处理:XGBoost 可以实现并行处理,相比 GBM 有了速度的飞跃。 不过,需要注意 XGBoost 的并行不是 tree 粒度的并行,XGBoost 也是一次迭 代完才能进行下一次迭代的(第 t 次迭代的代价函数里包含了前面 t-1 次迭代 的预测值)。XGBoost 的并行是在特征粒度上的。决策树的学习最耗时的一个 步骤就是对特征的值进行排序(因为要确定最佳分割点)。因此 XGBoost 在 R 重定义了一个自己数据矩阵类 DMatrix。XGBoost 在训练之前,预先对数据进 行了排序,然后保存为 block 结构,后面的迭代中重复利用索引地使用这个结 构,获得每个节点的梯度,大大减小计算量。这个 block 结构也使得并行成为 了可能,在进行节点的分裂时,需要计算每个特征的增益,最终选增益最大的 那个特征去做分裂,那么各个特征的增益计算就可以开多线程进行。
高度灵活性:XGBoost 允许用户定义自定义优化目标和评价标准,它 对模型增加了一个全新的维度,所以我们的处理不会受到任何限制。
缺失值处理:XGBoost 内置处理缺失值的规则。 用户需要提供一个 和其它样本不同的值,然后把它作为一个参数传进去,以此来作为缺失值的取 值。XGBoost 在不同节点遇到缺失值时采用不同的处理方法,并且会学习未来 遇到缺失值时的处理方法。
剪枝:当分裂时遇到一个负损失时,传统 GBDT 会停止分裂。因此传 统 GBDT 实际上是一个贪心算法。XGBoost 会一直分裂到指定的最大深度 (max_depth),然后回过头来剪枝。如果某个节点之后不再有正值,它会去除 这个分裂。这种做法的优点,当一个负损失(如-2)后面有个正损失(如+10) 的时候,就显现出来了。GBM 会在-2 处停下来,因为它遇到了一个负值。但是 XGBoost 会继续分裂,然后发现这两个分裂综合起来会得到+8,因此会保留这 两个分裂。
内置交叉验证:XGBoost 允许在每一轮 boosting 迭代中使用交叉验 证。因此,可以方便地获得最优 boosting 迭代次数。而传统的 GBDT 使用网格 搜索,只能检测有限个值
6.3.1 XGBoost数据预处理
#读取训练数据集与测试数据集
taiwan<- read.csv("D:/bigdatahw/算法/作业/card1.csv",head=TRUE,sep=',') #读取台湾信用数据
set.seed(1234) #设置随机种子,可以重复实验结果
tra=sample(1:nrow(taiwan), round(0.8* nrow(taiwan))) #抽取80%,24000个数据作为训练集
train=taiwan[tra,-1]
test=taiwan[-tra,-1]
#独热编码分类特征
ohe_feats = c('SEX', 'EDUCATION', 'MARRIAGE')
train$SEX<-as.factor(train$SEX)
train$EDUCATION<-as.factor(train$EDUCATION)
train$MARRIAGE<-as.factor(train$MARRIAGE)
dummies <- dummyVars(~ SEX + EDUCATION + MARRIAGE, data = train)
df_all_ohe <- as.data.frame(predict(dummies, newdata = train))
train <- cbind(df_all_ohe,train[,-c(2,3,4)])
ohe_feats = c('SEX', 'EDUCATION', 'MARRIAGE')
test$SEX<-as.factor(test$SEX)
test$EDUCATION<-as.factor(test$EDUCATION)
test$MARRIAGE<-as.factor(test$MARRIAGE)
dummies <- dummyVars(~ SEX + EDUCATION + MARRIAGE, data = test)
df_all_ohe <- as.data.frame(predict(dummies, newdata = test))
test<- cbind(df_all_ohe,test[,-c(2,3,4)])
#切分训练特征与回归特征
x<-train[,1:33]
y<-train[,34]
x<-apply(x,2,as.numeric) #将x的列变量转化为数字型,xgboost对数据类型要求严格
y<-as.numeric(y) #将y也转化为数字型变量
6.3.2 XGBoost实证检验
# xgboost训练过程
#也可以利用函数xgb.cv对数据进行交叉验证分析,利用交叉验证确定均方误差,
#利用交叉检验确定最佳迭代次数,利用10折交叉验证
cv.res<-xgb.cv(data=x,label=y,max.depth=2,eta=1,nround=15,objective='binary:logistic',nfold=10)
## [1] train-error:0.178583+0.000810 test-error:0.179375+0.007181
## [2] train-error:0.177801+0.000793 test-error:0.178583+0.008006
## [3] train-error:0.179069+0.001651 test-error:0.181583+0.008055
## [4] train-error:0.177750+0.001285 test-error:0.179042+0.008811
## [5] train-error:0.177565+0.001132 test-error:0.179375+0.009150
## [6] train-error:0.177514+0.001034 test-error:0.179334+0.009210
## [7] train-error:0.177310+0.001087 test-error:0.179583+0.009430
## [8] train-error:0.177361+0.001135 test-error:0.179042+0.009140
## [9] train-error:0.176968+0.001048 test-error:0.178833+0.008885
## [10] train-error:0.176893+0.001019 test-error:0.180375+0.008211
## [11] train-error:0.177074+0.000786 test-error:0.180000+0.008580
## [12] train-error:0.176866+0.000871 test-error:0.180292+0.008904
## [13] train-error:0.176616+0.001061 test-error:0.180458+0.008542
## [14] train-error:0.176717+0.000971 test-error:0.180500+0.008186
## [15] train-error:0.176495+0.000946 test-error:0.179750+0.007692
cv.res <- as.data.frame(cv.res$evaluation_log)
cv.res<-melt(cv.res[,c(1,2,4)],id = c("iter"),
variable.name = "type",
value.name = "cases",
na.rm = TRUE) #控制两列变量在新表中不动新生成的变量用case标识
ggplot(data=cv.res, aes(x=iter, y=cases, group=type, colour=type)) +
geom_line(size=1) +
geom_point() +
xlab("决策树棵数") + ylab("均方误差")+
ggtitle('交叉检验确定最优棵数')+
theme(plot.title = element_text(hjust =0.5,family="myFont",size=20,color="red"),
panel.background=element_rect(fill='aliceblue',color='black'),panel.grid.minor = element_blank())
#可以从10折交叉验证结果来看,当决策树数量(也就是迭代次数)
#到达8次后测试误差率开始上升说明XGBoost模型开始过于复杂,
#甚至出现了一点过拟合迹象因此选择决策树棵数也就是迭代次数为8次。
#定义XGBoost模型测试集结果评价函数,
#包含Accuracy,recall,precision,F_measure四个评价指标
#Accuracy总正确率,recall后验准确率,precision先验准确率,F_measure指数
index2=function(table) {
Accuracy=table[1,1]+table[2,2]
precision=table[2,2]/sum(table[,2])
recall=table[2,2]/sum(table[2,])
F_measure=2*precision*recall/(precision+recall)#计算Recall,Precision和F-measure
results=data.frame(Accuracy=Accuracy,recall=recall,precision=precision,F_measure=F_measure)
return(results)
}
timestart<-Sys.time();
bst<-xgboost(data=x,label=y,max.depth=2,eta=1,nround=8,objective='binary:logistic')
## [1] train-error:0.178500
## [2] train-error:0.178000
## [3] train-error:0.179375
## [4] train-error:0.178583
## [5] train-error:0.177208
## [6] train-error:0.178125
## [7] train-error:0.177875
## [8] train-error:0.177208
#在此处,根据交叉验证结果我们选取最大深度为2,学习速率为1,
#决策树棵树为10,也就是迭代次数为10,目标函数是基于二分类问
#题的logistic损失进行模型建立。
timeend<-Sys.time()
runningtime<-timeend-timestart
print(runningtime) #运行时间
## Time difference of 0.192559 secs
#利用predict函数进行预测
test<-apply(test,2,as.numeric)
pred<-predict(bst,test[,-34])
pred1 = ifelse(pred>0.5,1,0) #转化为分类变量0-1
true<-as.factor(test[,34])
table_XG=table(true,pred1)/nrow(test) #混淆数量矩阵
table_XG #从混淆矩阵中看出并不好
## pred1
## true 0 1
## 0 0.73083333 0.03650000
## 1 0.15000000 0.08266667
a=index2(table_XG) #预测准确率为0.771%,速度很快
a
## Accuracy recall precision F_measure
## 1 0.8135 0.3553009 0.6937063 0.4699195
#绘制ROC曲线
xgb_lr.train.modelroc <- roc(test[,34], pred)
plot(xgb_lr.train.modelroc,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)
#XGBoost变量重要性
model <- xgb.dump(bst, with.stats = T)
model[1:10]
## [1] "booster[0]"
## [2] "0:[f15<1.5] yes=1,no=2,missing=1,gain=2459.88,cover=6000"
## [3] "1:[f16<1.5] yes=3,no=4,missing=3,gain=502.502,cover=5379.5"
## [4] "3:leaf=-1.43651,cover=4927.25"
## [5] "4:leaf=-0.334253,cover=452.25"
## [6] "2:[f17<-0.5] yes=5,no=6,missing=5,gain=34.9331,cover=620.5"
## [7] "5:leaf=-0.186667,cover=36.5"
## [8] "6:leaf=0.817094,cover=584"
## [9] "booster[1]"
## [10] "0:[f29<390.5] yes=1,no=2,missing=1,gain=250.48,cover=4031.08"
# 获得特征的真实名称
names <- dimnames(train)[[2]]
# 计算特征重要性矩阵
importance_matrix <- xgb.importance(names, model = bst)
# 制图
xgb.ggplot.importance(importance_matrix[1:10,], rel_to_first = TRUE)+ylab('Gain')
xgb.plot.tree(model = bst,n_first_tree = 1,plot_width = 600,plot_height = 600)
#查看消耗内存
mem_change(xgboost(data=x,label=y,max.depth=2,eta=1,nround=12,objective='binary:logistic'))
## [1] train-error:0.178500
## [2] train-error:0.178000
## [3] train-error:0.179375
## [4] train-error:0.178583
## [5] train-error:0.177208
## [6] train-error:0.178125
## [7] train-error:0.177875
## [8] train-error:0.177208
## [9] train-error:0.177542
## [10] train-error:0.177833
## [11] train-error:0.177292
## [12] train-error:0.176708
## 95.9 kB
6.3.3 XGBoost模型优化
###利用XGBoost构造新的特征提高分类效率
train <- data.matrix(train)
test <- data.matrix(test)
new.features.train <- xgb.create.features(model = bst, train[,-34])
# 生成xgboost构造的新特征组合,训练集
new.features.test <- xgb.create.features(model = bst, test[,-34])
# 生成xgboost构造的新特征组合,测试集
newdtrain <- as.data.frame(as.matrix(new.features.train))
# 将训练集的特征组合转化为dataframe格式
newdtest <- as.data.frame(as.matrix(new.features.test))
# 将测试集的特征组合转化为dataframe格式
newtraindata <- cbind(newdtrain,y=train[,34])
# 将训练集的自变量和因变量合并
newtestdata <- cbind(newdtest,y=test[,34])
# 将测试集的自变量和因变量合并
# 对训练集进行预测
x1<-newtraindata[,1:58]
y1<-newtraindata[,59]
x1<-apply(x1,2,as.numeric)
#将x的列变量转化为数字型,xgboost对数据类型要求严格
y1<-as.numeric(y1) #将y也转化为数字型变量
cv.res<-xgb.cv(data=x1,label=y1,max.depth=2,eta=1,nround=15,objective='binary:logistic',nfold=10)
## [1] train-error:0.178500+0.001203 test-error:0.178500+0.010822
## [2] train-error:0.176875+0.001102 test-error:0.176875+0.009913
## [3] train-error:0.178482+0.001379 test-error:0.178791+0.010053
## [4] train-error:0.177597+0.001165 test-error:0.177917+0.009995
## [5] train-error:0.177009+0.001166 test-error:0.178125+0.009924
## [6] train-error:0.176782+0.001129 test-error:0.177708+0.009737
## [7] train-error:0.176500+0.001362 test-error:0.177792+0.009212
## [8] train-error:0.176467+0.001486 test-error:0.177583+0.010112
## [9] train-error:0.176287+0.001548 test-error:0.177792+0.009536
## [10] train-error:0.176273+0.001468 test-error:0.178292+0.009964
## [11] train-error:0.176222+0.001279 test-error:0.178000+0.010616
## [12] train-error:0.176222+0.001311 test-error:0.178042+0.010445
## [13] train-error:0.176190+0.001256 test-error:0.178583+0.010487
## [14] train-error:0.176083+0.001230 test-error:0.178417+0.010156
## [15] train-error:0.176055+0.001287 test-error:0.178125+0.010551
#十折交叉检验确定迭代次数
bst<-xgboost(data=x1,label=y1,max.depth=2,eta=1,nround=20,objective='binary:logistic')
## [1] train-error:0.178500
## [2] train-error:0.176875
## [3] train-error:0.178958
## [4] train-error:0.177667
## [5] train-error:0.177167
## [6] train-error:0.176667
## [7] train-error:0.176542
## [8] train-error:0.177000
## [9] train-error:0.177000
## [10] train-error:0.177208
## [11] train-error:0.176875
## [12] train-error:0.176708
## [13] train-error:0.176417
## [14] train-error:0.176542
## [15] train-error:0.176208
## [16] train-error:0.175958
## [17] train-error:0.175833
## [18] train-error:0.175958
## [19] train-error:0.175958
## [20] train-error:0.175833
newtestdata<-apply(newtestdata,2,as.numeric)
pred<-predict(bst,newtestdata[,-59])
pred1 = ifelse(pred>0.5,1,0) #转化为分类变量0-1
true<-as.factor(newtestdata[,59])
table_XG=table(true,pred1)/nrow(test) #混淆数量矩阵
table_XG
## pred1
## true 0 1
## 0 0.72716667 0.04016667
## 1 0.14833333 0.08433333
a=index2(table_XG) #预测准确率为0.771%,速度很快
a
## Accuracy recall precision F_measure
## 1 0.8115 0.3624642 0.6773762 0.4722352
#绘制ROC曲线
xgb_lr.train.modelroc <- roc(newtestdata[,59], pred)
plot(xgb_lr.train.modelroc,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)
6.4分类算法对比
先不考虑信贷的实际问题,单纯比较算法性能来讲,集成算法的对比表如下表所示,可以看出单从准确率上看,算法之间差距并不是很大,说明在集成算法上可 能都已经逼近了数据本身应有的特征,无法有大的改进,但值得注意的是,随机森林和 Adaboost 都需要进行多棵决策树的生成,迭代次数较多,成千上百次,而XGBoost只需要进行少量的迭代次数,在本次试验中仅需要8次。而且运行时间上XGBoost的多线程并行和基于其block的索引数据结构运行,也发挥了极大作用。比Adaboost缩短时间达到了近400倍,而比随机森林缩短时间近200倍。在本次信贷的数据分析中,XGBoost更有调节阈值后可以更加符合银行的商业要求,更加准确的识别出违约人。
\(~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\)表1-2 算法比较表
随机森林 | Adaboost | XGBoost | |
---|---|---|---|
Accuracy | 0.81 | 0.82 | 0.82 |
recall | 0.37 | 0.34 | 0.36 |
precision | 0.62 | 0.67 | 0.68 |
F_measure | 0.46 | 0.45 | 0.48 |
运行时间(s) | 44.46 | 85.42 | 0.21 |