首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >R RF不平衡类别与训练相比,未见数据的负值预测值较低

R RF不平衡类别与训练相比,未见数据的负值预测值较低
EN

Stack Overflow用户
提问于 2019-01-23 19:53:06
回答 1查看 206关注 0票数 1

我已经建立了一个随机森林模型,用于预测客户是否正在进行与欺诈有关的操作。这是一个很大的,相当不平衡的样本,有3%的欺诈案例,我想预测少数类别(欺诈)。

我平衡数据(每个50%)并构建RF。到目前为止,我有一个很好的模型,总体准确率约为80%,正确预测的欺诈率为+70%。但是,当我在未见过的数据(测试)上尝试该模型时,尽管总体准确率很好,但与训练数据相比,负预测值(欺诈)真的很低(13%仅比+70%)。

我尝试了增加样本大小,增加平衡类别,调整RF参数,...,但它们都没有很好地工作,结果相似。不知何故,我是不是太适应了?如何提高对未见数据的欺诈检测(负预测值)?

以下是代码和结果:

代码语言:javascript
复制
set.seed(1234)

#train and test sets
model <- sample(nrow(dataset), 0.7 * nrow(dataset))
train <- dataset[model, ]
test <- dataset[-model, ]
    #Balance the data
balanced <- ovun.sample(custom21_type ~ ., data = train, method = "over",p = 0.5, seed = 1)$data

table(balanced$custom21_type)

   0    1 
5813 5861

#build the RF
rf5 = randomForest(custom21_type~.,ntree = 100,data = balanced,importance = TRUE,mtry=3,keep.inbag=TRUE)
rf5

Call:
 randomForest(formula = custom21_type ~ ., data = balanced, ntree = 100,      importance = TRUE, mtry = 3, keep.inbag = TRUE) 
               Type of random forest: classification
                     Number of trees: 100
No. of variables tried at each split: 3

        OOB estimate of  error rate: 21.47%
Confusion matrix:
     0    1 class.error
0 4713 1100   0.1892310
1 1406 4455   0.2398908

#test on unseen data
predicted <- predict(rf5, newdata=test)
confusionMatrix(predicted,test$custom21_type)
Confusion Matrix and Statistics

          Reference
Prediction     0     1
         0 59722   559
         1 13188  1938

               Accuracy : 0.8177          
                 95% CI : (0.8149, 0.8204)
    No Information Rate : 0.9669          
    P-Value [Acc > NIR] : 1               

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

            Sensitivity : 0.8191          
            Specificity : 0.7761          
         Pos Pred Value : 0.9907          
         Neg Pred Value : 0.1281          
             Prevalence : 0.9669          
         Detection Rate : 0.7920          
   Detection Prevalence : 0.7994          
      Balanced Accuracy : 0.7976          

       'Positive' Class : 0     
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-01-26 02:52:20

首先,我注意到您没有使用任何交叉验证。包括这将有助于增加用于训练的数据的变化,并将有助于减少过拟合。此外,我们将使用C.50代替randomForest,因为它更健壮,并且对类型1错误提供了更多的惩罚。

你可能会考虑的一件事是,实际上在训练数据中不是50:50的平衡分裂,而是更多的80-20平衡。这是为了不对欠平衡类进行过采样。我确信这会导致过度拟合,并导致您的模型无法将新的示例归类为负值。

在创建重新平衡数据(p=.2)后运行此命令

代码语言:javascript
复制
library(caret)
#set up you cross validation
Control <- trainControl(
summaryFunction = twoClassSummary, #displays model score not confusion matrix
classProbs = TRUE, #important for the summaryFunction
verboseIter = TRUE, #tones down output
savePredictions = TRUE, 
method = "repeatedcv", #repeated cross validation, 10 folds, 3 times
repeats = 3,
number = 10,
allowParallel = TRUE

)

现在我在评论中看到你所有的变量都是绝对的。这对于NaiveBayes算法来说是最好的。但是,如果您有任何数字数据,则需要按照标准过程进行预处理(缩放、归一化和NA输入)。我们还将实现一个网格搜索过程。

如果你的数据都是分类的

代码语言:javascript
复制
model_nb <- train(
x = balanced[,-(which(colnames(balanced))%in% "custom21_type")],
y= balanced$custom21_type,
metric = "ROC",
method = "nb", 
trControl = Control,
tuneGrid = data.frame(fL=c(0,0.5,1.0), usekernel = TRUE, 
adjust=c(0,0.5,1.0)))

如果您喜欢RF方法(如果数据是数字,请确保进行预处理)

代码语言:javascript
复制
model_C5 <- train(
x = balanced[,-(which(colnames(balanced))%in% "custom21_type")],
y= balanced$custom21_type,
metric = "ROC",
method = "C5.0", 
trControl = Control,
tuneGrid = tuneGrid=expand.grid(.model = "tree",.trials = c(1,5,10), .winnow = F)))

现在我们预测

代码语言:javascript
复制
C5_predict<-predict(model_C5, test, type = "raw")
NB_predict<-predict(model_nb, test, type = "raw")
confusionMatrix(C5_predict,test$custom21_type)
confusionMatrix(nb_predict,test$custom21_type)

编辑:

尝试调整下面的成本矩阵。这个错误所做的是惩罚类型2的错误,是类型1错误的两倍。

代码语言:javascript
复制
cost_mat <- matrix(c(0, 2, 1, 0), nrow = 2)
rownames(cost_mat) <- colnames(cost_mat) <- c("bad", "good")
cost_mod <- C5.0( x = balanced[,-(which(colnames(balanced))%in% 
"custom21_type")],
y= balanced$custom21_type,
             costs = cost_mat)
summary(cost_mod)

编辑2:

代码语言:javascript
复制
predicted <- predict(rf5, newdata=test, type="prob")

将为您提供每个预测的实际概率。默认截止值为.5。也就是说,.5以上的所有内容都将被归类为0,而低于1的所有内容都将被归类为1。因此,您可以调整这个分界值,以帮助处理不平衡的类。

代码语言:javascript
复制
ifelse(predicted[,1] < .4, 1, predicted[,1])
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54326676

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档