我已经建立了一个随机森林模型,用于预测客户是否正在进行与欺诈有关的操作。这是一个很大的,相当不平衡的样本,有3%的欺诈案例,我想预测少数类别(欺诈)。
我平衡数据(每个50%)并构建RF。到目前为止,我有一个很好的模型,总体准确率约为80%,正确预测的欺诈率为+70%。但是,当我在未见过的数据(测试)上尝试该模型时,尽管总体准确率很好,但与训练数据相比,负预测值(欺诈)真的很低(13%仅比+70%)。
我尝试了增加样本大小,增加平衡类别,调整RF参数,...,但它们都没有很好地工作,结果相似。不知何故,我是不是太适应了?如何提高对未见数据的欺诈检测(负预测值)?
以下是代码和结果:
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 发布于 2019-01-26 02:52:20
首先,我注意到您没有使用任何交叉验证。包括这将有助于增加用于训练的数据的变化,并将有助于减少过拟合。此外,我们将使用C.50代替randomForest,因为它更健壮,并且对类型1错误提供了更多的惩罚。
你可能会考虑的一件事是,实际上在训练数据中不是50:50的平衡分裂,而是更多的80-20平衡。这是为了不对欠平衡类进行过采样。我确信这会导致过度拟合,并导致您的模型无法将新的示例归类为负值。
在创建重新平衡数据(p=.2)后运行此命令
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输入)。我们还将实现一个网格搜索过程。
如果你的数据都是分类的
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方法(如果数据是数字,请确保进行预处理)
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)))现在我们预测
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错误的两倍。
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:
predicted <- predict(rf5, newdata=test, type="prob")将为您提供每个预测的实际概率。默认截止值为.5。也就是说,.5以上的所有内容都将被归类为0,而低于1的所有内容都将被归类为1。因此,您可以调整这个分界值,以帮助处理不平衡的类。
ifelse(predicted[,1] < .4, 1, predicted[,1])https://stackoverflow.com/questions/54326676
复制相似问题