楼主: 阿扁V5
8085 4

[数据挖掘理论与案例] 用R测试逻辑回归、决策树、随机森林、神经网络、SVM,及集成学习的分类性能(一) [推广有奖]

  • 1关注
  • 43粉丝

版主

山野小子

已卖:965份资源

副教授

94%

还不是VIP/贵宾

-

威望
0
论坛币
-28984312 个
通用积分
3823.6007
学术水平
108 点
热心指数
119 点
信用等级
91 点
经验
49334 点
帖子
1168
精华
1
在线时间
651 小时
注册时间
2013-3-22
最后登录
2024-3-17

楼主
阿扁V5 学生认证  发表于 2017-9-25 10:17:22 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币
前言
      本人最近出于公司的业务需求,要构建反欺诈模型,所以测试了逻辑回归、决策树、随机森林、神经网络、SVM等一系列单一机器学习算法,以及集成学习等方法,在这里将实现方式分享给各位,毕竟业务场景不一样,结果可能完全相悖,本文的目的仅希望各位在实现各类算法时能较快速的上手。
    由于数据的商业保密性,此处不贴出数据集,不喜勿喷。好了,废话不多说,开始正文。
数据初识
        我整合的数据集500多个变量,包含申请信息、贷款信息、第三方数据等,目标是是否欺诈,FRAUD_FLAG就是我们的目标变量。以下是比较初步的数据整理

数据初识
  1. ############################# 数据读取 ###########################################

  2. # 读取制表分隔符文本类数据
  3. fraud <- read.table('F:/pxw/R-3.4.1/DATA/TB_FRAUD_MAIN_DATA_INNER_NMISS3.csv',
  4.                     header =TRUE,stringsAsFactors=FALSE, sep=",");

  5. summary(fraud);
  6. # 缺失值替换为0
  7. fraud[is.na(fraud)]=0
  8. # 选取变量
  9. # FRAUD_FLAG <- fraud$FRAUD_FLAG
  10. # fraud <- cbind(FRAUD_FLAG,fraud[,435:462])
  11. # 转换为数据框
  12. fraud <- as.data.frame(fraud)
  13. # 将预测目标转换为因子型

  14. fraud$FRAUD_FLAG <- as.factor(fraud$FRAUD_FLAG)
  15. # 统计字符变量占比
  16. # round(prop.table(table(fraud$DKFS))*100,digits = 1)
  17. # 按applyID排序,并去除一些没有信息的变量,如申请编号之类的
  18. fraud <- subset(fraud[order(fraud$applyID),],
  19.                 select = c(-applyID,-report_id,-APPLYTIME,-ZJYCJYSJ,-fkrq,-htbh))
  20. table(fraud$FRAUD_FLAG)

  21. # 20471   854
  22. prop.table(table(fraud$FRAUD_FLAG))
  23. # 0          1
  24. # 0.95995311 0.04004689
复制代码

        如上所示,2万多笔,欺诈比例约4%左右,算是比较低的了,这还是放宽欺诈定义的结果,按照严格的定义,欺诈比例只有6‰左右。
  1. # 各种R包的准备
  2. library(lattice)
  3. library(ggplot2)
  4. library(e1071)
  5. # roc曲线包
  6. library(pROC)
  7. # smote抽样包
  8. library(DMwR)
  9. # 机器学习模型参数自动调整包/数据集划分
  10. library(caret)
  11. # 随机森林包
  12. library(randomForest)
  13. # 混淆矩阵包
  14. library(gmodels)
复制代码




变量选择
        在建模之前我们需要进行数据质量的检验、探索分析等,由于此文的目的是各类机器学习算法的快速实现,此处略过,直接来到变量的选择。
        变量选择之前,由于我们的目标变量是严重失衡数据,我们需要先利用somte方法对少类进行过采样,敲黑板了,过采样的方法非常重要,若不进行过采样,可能完全没法识别欺诈样本,当然,这跟我们的数据质量、数据广度、数据浓度是有关系的。

  1. # smote抽样
  2. # smote重采样,k表示少数类产生新样本的最近邻参数,默认是5,
  3. # perc.over表示对少数类样本过采样产生新样本的百分比,比如perc.over=80,在少数类样本=100的情况下,
  4. # 产生80个少数类样本,总计180个少数类样本
  5. # perc.under表示对多数类样本欠采样产生新样本的百分比,比如perc.under=300,在少数类样本=100,且perc.over=200的情况下,
  6. # 将从多数类样本中抽取100*200%*300%=600个多数类的样本,总计600个多数类样本
  7. #设置随机数种子,保证实验可重复性
  8. set.seed(500)
  9. train_smote_set1 <- SMOTE(FRAUD_FLAG ~ ., data=fraud, k=10, perc.over = 100,  perc.under = 115)

  10. table(train_smote_set1$FRAUD_FLAG)
  11. prop.table(table(train_smote_set1$FRAUD_FLAG))
复制代码

        变量的重要性我们可以通过随机森林实现,由randomforest函数的importance来指定,随机森林变量重要性的计算方式可以通过4种方法,分类问题可以选基于OOB,计算预测误差率的MeanDecreaseAccuracy方法,和基于样本拟合模型,计算Gini系数的MeanDecreaseGini方法;回归问题可以类似的选择%IncMSE和IncNodePrity方法。此处我们选择基于信息增益原理的Gini系数。

  1. # 设置随机数种子,可重复
  2. set.seed(300)
  3. # formula目标变量和自变量方程
  4. # data是训练集
  5. # ntree树的数目,默认是500
  6. # mtry每次划分中随机选择的特征数,默认是变量数的平方根
  7. fraud_model1 <- randomForest(formula=FRAUD_FLAG ~ .,
  8.                             data=train_smote_set1,
  9.                             ntree=500,
  10.                             mtry=sqrt(ncol(fraud)),
  11.                             maxnotes=10,
  12.                             importance=TRUE)
  13. fraud_model1

  14. # Call:
  15. #   randomForest(formula = FRAUD_FLAG ~ ., data = train_smote_set1,      ntree = 500, mtry = sqrt(ncol(fraud)), maxnotes = 10, importance = TRUE)
  16. # Type of random forest: classification
  17. # Number of trees: 500
  18. # No. of variables tried at each split: 23
  19. #
  20. # OOB estimate of  error rate: 21.56%
  21. # Confusion matrix:
  22. #   0    1 class.error
  23. # 0 672  310   0.3156823
  24. # 1 270 1438   0.1580796
  25. 我们可以看到训练模型的误差率是21.56%,算算马马虎虎的。

  26. # 查看变量重要性,图片无法上传
  27. varImpPlot(fraud_model1,main='随机森林特征选择')
复制代码
  1. # 按GINI系数对变量重要性排序
  2. x <- sort(importance(fraud_model1)[,4],decreasing = T)
  3. # 提取GINI值大于10的列名
  4. y <- colnames(as.data.frame(t(subset(x,x>=10))))
  5. # 合并欺诈标识
  6. y[length(y)+1] <- "FRAUD_FLAG"
  7. # 提取对应的变量作为建模表
  8. fraud_imp_var <- subset(fraud,select = y)
复制代码


      这里Gini系数≥10的变量一共34个变量,接下来就是数据集的切分了。事实上我们还可以进行lasso或弹性网络或逐步回归进一步筛选变量,我最后的探索结果表明,基于这样一个数据量的数据集,不太适合采用非常高维的数据,很容易造成overfitting的现象,而在少变量的情形下(10个以内),逻辑回归更加稳定。


数据划分
  1. # -------------------------------- 数据划分 --------------------------------------

  2. # 设置随机数种子,保证实验可重复性
  3. set.seed(1234)
  4. # 调用caret包的 createDataPartition 函数划分训练和测试集,y是分层抽样变量,p为抽样比
  5. # 若有多个分层变量,可为每个分层变量指定抽样比,若只有一个抽样比,则每一层抽样比例相同

  6. spilt_index <- createDataPartition(y=c(fraud_imp_var$FRAUD_FLAG),
  7.                                    p=c(0.7),list = FALSE)
  8. train_set <- fraud_imp_var[spilt_index,]
  9. test_set <- fraud_imp_var[-spilt_index,]

  10. # 统计占比
  11. prop.table(table(train_set$FRAUD_FLAG))

  12. # 0         1
  13. # 0.9596731 0.0403269

  14. prop.table(table(test_set$FRAUD_FLAG))

  15. # 0          1
  16. # 0.96060653 0.03939347
复制代码

        如上述结果,测试集和训练集的欺诈比例都在4%左右。准备工作做完了,就开始正式建模。


逻辑回归
  1. # -------------------------------- 逻辑回归 --------------------------------------

  2. set.seed(500)
  3. train_smote_set <- SMOTE(FRAUD_FLAG ~ ., data=train_set, k=10, perc.over = 100,  perc.under = 200)
  4. table(train_smote_set$FRAUD_FLAG)
  5. prop.table(table(train_smote_set$FRAUD_FLAG))

  6. logit_model <- glm(FRAUD_FLAG ~.,family=binomial(link='logit'),data=train_smote_set)
  7. summary(logit_model)

  8. # Call:
  9. #   glm(formula = FRAUD_FLAG ~ ., family = binomial(link = "logit"),
  10. #       data = train_smote_set)
  11. #
  12. # Deviance Residuals:


  13. #   Min        1Q    Median        3Q       Max  
  14. # -2.51711  -0.95808  -0.02472   0.99347   2.32549  
  15. #
  16. # Coefficients: (3 not defined because of singularities)
  17. # Estimate Std. Error z value Pr(>|z|)   
  18. # (Intercept)               -3.268e+00  3.815e-01  -8.566  < 2e-16 ***

  19. #   VAR_SUM                    2.429e-01  2.855e-02   8.506  < 2e-16 ***
  20. #   SQCS                       4.512e-01  3.608e-01   1.251 0.211009   

  21. # 。。。。。
  22. #   Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
  23. #
  24. # (Dispersion parameter for binomial family taken to be 1)
  25. #
  26. # Null deviance: 3338.2  on 2407  degrees of freedom
  27. # Residual deviance: 2802.4  on 2376  degrees of freedom
  28. # AIC: 2866.4
  29. # Number of Fisher Scoring iterations: 5

  30. # 逐步回归重选择变量,direction可以选back和forward以及both即逐步回归
  31. logit_model_step <- step(logit_model,direction = 'both',trace = T)
  32. # 将预测概率转换为0-1变量
  33. logit_model_pred=predict(logit_model, test_set,type='response')
  34. logit_model_pred1 <- round(logit_model_pred)

  35. # 输出混淆矩阵
  36. CrossTable(test_set$FRAUD_FLAG,logit_model_pred1,
  37.            prop.chisq = F, prop.c = F,prop.r = T,
  38.            dnn = c('ACTUAL FRAUD','PREDICTED FRAUD'))



  39. # 将预测目标转换为数值型,才能计算auc
  40. test_numeric <- as.numeric(test_set$FRAUD_FLAG)
  41. logit_model_pred1 <- as.numeric(logit_model_pred1)
  42. # 调用pROC包的roc函数
  43. fraud_log_auc <- roc(test_set$FRAUD_FLAG,logit_model_pred1)
  44. # 输出auc曲线面积
  45. print(fraud_log_auc)

  46. # 画auc图
  47. plot(fraud_log_auc,ylim=c(0,1),print.thres=TRUE,main=paste('AUC',round(fraud_log_auc$auc[[1]],2)))
  48. abline(h=1,col="blue",lwd=2)
  49. abline(h=0,col="red",lwd=2)
复制代码
      AUC面积的计算还可以调用ROCR包来计算,严格来说,ROCR得到的才是真正的AUC,此处计算的只是一个最佳点和原点以及顶点的三角形面积,所以通常比ROCR的结果要小。
       这里我们可以看到模型在测试集的auc面积,表现相当一般,可以说是比较差,才0.64。通常来说,auc面积=1,是非常完美的分类器,在0.9-1之间是很优秀的分类器,在0.8-0.9之间是一个比较良好的分类器,在0.7-0.8之间则是一般的的分类器,0.6-0.7之间则需要谨慎使用了,0.6以下就是非常坏的分类器了,基本上跟随机猜没多少区别。

随机森林
  1. # -------------------------------- 一般randomForest --------------------------------------
  2. # smote抽样
  3. # smote重采样,k表示少数类产生新样本的最近邻参数,默认是5,
  4. # perc.over表示对少数类样本过采样产生新样本的百分比,比如perc.over=80,在少数类样本=100的情况下,
  5. # 产生80个少数类样本,总计180个少数类样本
  6. # perc.under表示对多数类样本欠采样产生新样本的百分比,比如perc.under=300,在少数类样本=100,且perc.over=200的情况下,
  7. # 将从多数类样本中抽取100*200%*300%=600个多数类的样本,总计600个多数类样本
  8. set.seed(500)

  9. train_smote_set <- SMOTE(FRAUD_FLAG ~ ., data=train_set, k=10, perc.over = 100,  perc.under = 130)
  10. table(train_smote_set$FRAUD_FLAG)
  11. prop.table(table(train_smote_set$FRAUD_FLAG))

  12. # 设置随机数种子,可重复
  13. set.seed(300)

  14. # formula目标变量和自变量方程
  15. # data是训练集
  16. # ntree树的数目,默认是500
  17. # mtry每次划分中随机选择的特征数,默认是变量数的平方根
  18. fraud_model <- randomForest(formula=FRAUD_FLAG ~.,
  19.                                  data=train_smote_set,
  20.                                  ntree=100,
  21.                                  mtry=sqrt(ncol(train_smote_set)),
  22.                             maxnotes=10)
  23. fraud_model
  24. # Call:
  25. #   randomForest(formula = FRAUD_FLAG ~ ., data = train_smote_set,      ntree = 100, mtry = sqrt(ncol(train_smote_set)), maxnotes = 10)
  26. # Type of random forest: classification
  27. # Number of trees: 100
  28. # No. of variables tried at each split: 6
  29. #
  30. # OOB estimate of  error rate: 21.3%
  31. # Confusion matrix:
  32. #   0    1 class.error
  33. # 0 536  246    0.314578
  34. # 1 177 1027    0.147010


  35. # fraud_model 训练模型
  36. # test_set测试集,必须与训练集一致
  37. # type可以是"response","prob","vote",分别表示输出预测向量是预测类别、预测概率或投票矩阵
  38. fraud_pred <- predict(fraud_model, test_set, type='response')
  39. # 输出混淆矩阵
  40. CrossTable(test_set$FRAUD_FLAG,fraud_pred,
  41.            prop.chisq = F, prop.c = F,prop.r = T,
  42.            dnn = c('ACTUAL FRAUD','PREDICTED FRAUD'))
  43. # 将预测目标转换为数值型,才能计算auc
  44. test_numeric <- as.numeric(test_set$FRAUD_FLAG)
  45. fraud_pred <- as.numeric(fraud_pred)
  46. # 调用pROC包的roc函数
复制代码

          尽管随机森林的表现依然不能让人满意,但至少比逻辑回归有所提升。

今天先写到这里,剩下的找时间再写~~~




二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝


已有 1 人评分论坛币 学术水平 热心指数 收起 理由
飞天玄舞6 + 20 + 3 + 3 精彩帖子

总评分: 论坛币 + 20  学术水平 + 3  热心指数 + 3   查看全部评分

憧憬机器学习的世界!

沙发
阿扁V5 学生认证  发表于 2017-9-25 10:19:41
不知道为什么,我这里看到文章里的代码有点乱

藤椅
woshimeilinda 发表于 2017-10-24 19:57:16
可以私信数据集吗?想根据你的文章做实验,给一部分数据可以吗?

板凳
阿扁V5 学生认证  发表于 2017-10-24 22:18:56 来自手机
woshimeilinda 发表于 2017-10-24 19:57
可以私信数据集吗?想根据你的文章做实验,给一部分数据可以吗?
抱歉,公司数据外发不了

报纸
fvfsfdsvdds 学生认证  发表于 2019-12-4 21:41:51
剩下的是不是没写啊楼主

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注cda
拉您进交流群
GMT+8, 2025-12-26 20:05