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

R中LDA模型预测异常:因子水平1被误判为0的问题排查

LDA模型全误判少数类的修复方案

从你的混淆矩阵能看到,模型完全把类别1的样本预测成0,本质是模型没学到任何区分两类的有效信息,结合你试过加减变量没用的情况,核心问题出在类别极度不平衡和特征区分度不足,下面是具体的修复步骤:

一、先解决类别不平衡问题

你的测试集里类别0占95%,训练集肯定也是极度不平衡的。LDA默认用样本比例作为先验概率,这种情况下模型会优先预测多数类来保证“好看的准确率”,完全忽略少数类。

1. 手动调整LDA先验概率

强制让模型平等看待两类,比如给两类各设50%的先验(可根据实际情况调整比例):

lda.model = lda(factor(Donation) ~ Age + Home + NumberOfChild, 
                data = dftrain, 
                prior = c(0.5, 0.5))

2. 平衡训练集样本

  • 过采样:复制少数类(类别1)的样本,让两类数量接近
  • 欠采样:随机删掉一部分多数类(类别0)样本
  • SMOTE合成样本:用DMwR包生成少数类的合成样本,避免过拟合:
library(DMwR)
# 生成平衡后的训练集:少数类过采样200%,多数类欠采样150%
dftrain_balanced = SMOTE(factor(Donation) ~ Age + Home + NumberOfChild, 
                         data = dftrain, 
                         perc.over = 200, 
                         perc.under = 150)
# 用平衡后的数据集训练LDA
lda.model = lda(factor(Donation) ~ ., data = dftrain_balanced)

二、检查特征是否真的有用

你加减变量没变化,说明当前特征在两类之间几乎没差异,根本没法帮模型区分:

1. 统计检验特征区分度

对每个特征做类间差异检验:

# 连续特征(Age、NumberOfChild)做t检验
t.test(Age ~ factor(Donation), data = dftrain)
t.test(NumberOfChild ~ factor(Donation), data = dftrain)

# 分类特征(Home)做卡方检验
chisq.test(table(dftrain$Home, dftrain$Donation))

如果所有检验的p值都远大于0.05,说明这些特征完全没用,必须换其他特征或者做特征工程。

2. 尝试特征变换/组合

比如创建交互项、对连续特征分箱:

# 添加Age和NumberOfChild的交互项
dftrain$Age_Child = dftrain$Age * dftrain$NumberOfChild
# 重新训练模型
lda.model = lda(factor(Donation) ~ Age + Home + NumberOfChild + Age_Child, data = dftrain)

三、调整模型或评估指标

1. 换用更适合不平衡数据的模型

LDA对数据假设(同协方差高斯分布)要求高,且不擅长处理不平衡数据,试试随机森林、XGBoost这类模型,它们自带处理不平衡的参数:

library(randomForest)
rf.model = randomForest(factor(Donation) ~ Age + Home + NumberOfChild, 
                        data = dftrain, 
                        classwt = c(0.1, 0.9))  # 给少数类更高权重

2. 别只看准确率!

不平衡数据集里准确率毫无意义,重点看类别1的召回率、F1值、ROC-AUC这些指标,这些才能反映模型对少数类的识别能力。

四、验证LDA的假设是否成立

LDA要求两类数据的协方差矩阵相近,如果不满足,模型效果会极差:

# 拆分两类样本的特征
train_0 = dftrain[dftrain$Donation == 0, c("Age", "Home", "NumberOfChild")]
train_1 = dftrain[dftrain$Donation == 1, c("Age", "Home", "NumberOfChild")]

# 打印协方差矩阵对比
print("类别0的协方差矩阵:")
print(cov(train_0))
print("类别1的协方差矩阵:")
print(cov(train_1))

如果协方差差异很大,改用QDA(二次判别分析),它不要求同协方差:

library(MASS)
qda.model = qda(factor(Donation) ~ Age + Home + NumberOfChild, data = dftrain)
predictions.qda = predict(qda.model, newdata = dftest)
caret::confusionMatrix(as.factor(predictions.qda$class), as.factor(dftest$Donation))

内容的提问来源于stack exchange,提问作者Isabella Clemandot

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 18:45:03