You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Naive Bayes模型始终无法预测S2类,仅输出S1/S3类的解决方法

解决Naive Bayes模型无法识别S2类的问题

问题概述

使用Naive Bayes模型对数据按SC_3ans_segment分为S1、S2、S3三类,但模型始终仅输出S1或S3的预测结果,混淆矩阵显示S2类的预测样本数为0。调整测试集规模后问题未得到改善。

代码复现

set.seed(2)
id <- sample(2, nrow(Data), prob = c(0.7, 0.3), replace = T)
Datatrain <- Data[id==1,]
Datatest <- Data[id==2,]

library(e1071)
library(caret)
y <- Datatrain$SC_3ans_segment
x <- Datatrain[, names(Datatrain) %in% c("TYPE_CONTRACTUALISATION","WEBSERVICE_MANUEL","REGION","RENFORT","ECO","TRANCHE_ANC_2021","GAR_PRODUIT","TRANCHE_AGE","SOU_GRP_SITUATION_FAMILLE","REGIME","Type_Distribution","PTF_2022","GAR_FORMULE_GROUPE")]
Data_nb_model <- caret::train(x,y,'nb',trControl=trainControl(method='cv',number=10))
Test_model <- predict(object=Data_nb_model, newdata=Datatest)
confusionMatrix(table(Test_model, Datatest$SC_3ans_segment))

模型输出

Confusion Matrix and Statistics

    Test_model    S1    S2    S3
    S1 10349  1023  4913
    S2     0     0     0
    S3  1637   231  1492

 Overall Statistics
                                      
           Accuracy : 0.6027          
             95% CI : (0.5959, 0.6096)
No Information Rate : 0.6101          
P-Value [Acc > NIR] : 0.9833          
                                      
              Kappa : 0.094           
                                      
Mcnemar's Test P-Value : <2e-16           

Statistics by Class:

                 Class: S1 Class: S2 Class: S3
Sensitivity             0.8634   0.00000   0.23294
Specificity             0.2250   1.00000   0.85891
Pos Pred Value          0.6355       NaN   0.44405
Neg Pred Value          0.5128   0.93617   0.69831
Prevalence              0.6101   0.06383   0.32604
Detection Rate          0.5268   0.00000   0.07595
Detection Prevalence    0.8290   0.00000   0.17104
Balanced Accuracy       0.5442   0.50000   0.54593

核心原因

从输出的Prevalence(患病率)可以看到,S2类在测试集中仅占6.38%,属于严重类别不平衡。Naive Bayes默认以整体准确率为优化目标,会倾向于预测样本量更大的类别(S1占61%),完全忽略小样本的S2类。

修复方案

1. 重采样训练集平衡类别

在训练阶段对小类进行过采样,或对大类进行欠采样,让各类别样本量均衡。利用caret的sampling参数实现:

# 过采样:对S2类重复采样,提升其样本占比
Data_nb_model <- caret::train(
  x, y, 'nb',
  trControl = trainControl(method='cv', number=10, sampling = "up"),
  metric = "Kappa"  # 用Kappa替代准确率,更适合不平衡数据的性能评估
)

# 欠采样:减少S1、S3类样本量,匹配S2的规模
Data_nb_model <- caret::train(
  x, y, 'nb',
  trControl = trainControl(method='cv', number=10, sampling = "down"),
  metric = "Kappa"
)

2. 自定义分类阈值

Naive Bayes默认用0.5的概率阈值判断类别,对于小类可降低阈值,让模型更容易输出S2类预测:

# 获取测试集的类别概率
Test_probs <- predict(Data_nb_model, newdata=Datatest, type="prob")

# 自定义阈值:降低S2的判断阈值(可根据实际效果调整)
Test_model_custom <- apply(Test_probs, 1, function(row) {
  if (row["S2"] > 0.1) {
    return("S2")
  } else {
    return(names(which.max(row[c("S1", "S3")])))
  }
})

# 重新生成混淆矩阵验证效果
confusionMatrix(table(Test_model_custom, Datatest$SC_3ans_segment))

3. 检查特征区分度

验证特征对S2类的区分能力,移除或替换无区分度的特征:

# 可视化每个特征在不同类别中的分布
library(ggplot2)
for (col in names(x)) {
  p <- ggplot(Datatrain, aes_string(x=col, fill="SC_3ans_segment")) +
    geom_bar(position="fill") +
    labs(title=paste(col, "按类别分布"))
  print(p)
}

如果某个特征在S2类中的分布与其他类几乎无差异,考虑移除该特征或补充更具区分度的特征。

4. 调整平滑参数

Naive Bayes的拉普拉斯平滑参数可能影响小类的概率计算,尝试调整fL参数优化:

# 测试不同平滑值对模型的影响
Data_nb_model <- caret::train(
  x, y, 'nb',
  trControl = trainControl(method='cv', number=10),
  tuneGrid = data.frame(fL = c(0, 0.5, 1, 2)),
  metric = "Kappa"
)

效果验证

调整后重新生成混淆矩阵,重点关注S2类的Sensitivity(召回率)是否提升,同时平衡整体Kappa值(综合各类别性能)。

内容的提问来源于stack exchange,提问作者Jia Hannah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 22:57:27