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

使用e1071包的SVM调参后准确率不升反降,求原因及解决办法

关于SVM调参后准确率骤降的问题分析与解决建议

我来帮你拆解这个问题——从你的代码和混淆矩阵来看,调参后的模型直接退化到只预测多数类(类别2),准确率刚好等于测试集中类别2的占比(47.6%),这是核心症结所在。下面我梳理可能的原因,再给出具体的操作建议:

可能的原因

  • 特征未做尺度归一化:SVM(尤其是径向基核)对特征尺度极其敏感。如果你的特征之间数值范围差异悬殊,模型会偏向于尺度大的特征,导致学习失效;极端参数下甚至会直接退化到预测多数类。
  • 参数搜索范围极端不合理:你尝试的gamma=10^10、cost=10^100这类参数完全脱离实际。gamma过大时,径向基核会变得非常"尖锐",每个样本都会成为支持向量,模型彻底过拟合;cost过大则会让模型为了不犯任何错误而过拟合,而你最初选的cost=0.1过小,模型对错误的容忍度太高,直接选择最省心的多数类预测。
  • 类别不平衡导致CV结果失真:从测试集的混淆矩阵来看,类别2的样本占比接近48%,如果训练集也是类似分布,普通的10折交叉验证可能无法捕捉到少数类的信息,导致tune.svm选出的参数偏向于优化整体准确率(即预测多数类)。
  • 交叉验证的评估指标问题:tune.svm默认用分类准确率作为评估指标,在类别不平衡的场景下,这个指标会误导模型选择预测多数类的策略,而非真正的泛化能力。

具体操作建议

1. 先做特征标准化处理

这是SVM任务的必备步骤,一定要先对训练集的特征做标准化,再用同样的均值和标准差转换测试集:

# 对训练集特征标准化(排除目标变量rating)
train_scaled <- scale(train[, -which(names(train) == "rating")])
# 合并标准化后的特征和目标变量
train_scaled_df <- cbind(data.frame(rating = train$rating), train_scaled)

# 用训练集的标准化参数处理测试集
test_scaled <- scale(test[, -which(names(test) == "rating")], 
                     center = attr(train_scaled, "scaled:center"),
                     scale = attr(train_scaled, "scaled:scale"))
test_scaled_df <- cbind(data.frame(rating = test$rating), test_scaled)

之后用标准化后的数据集重新训练和调参。

2. 调整合理的参数搜索范围

放弃极端的参数值,选择SVM常用的参数区间:

# 合理的gamma和cost范围,搭配分层交叉验证适配类别不平衡
tune_result <- tune.svm(rating ~ ., 
                        data = train_scaled_df,
                        kernel = "radial",
                        gamma = 10^c(-3, -2, -1, 0, 1),  # 0.001到10
                        cost = 10^c(-2, -1, 0, 1, 2),     # 0.01到100
                        cross = 10,
                        sampling = "stratified")
summary(tune_result)

3. 解决类别不平衡问题

  • 设置类别权重:在svm函数中给少数类更高的权重,强制模型关注少数类:
# 假设类别1和3是少数类,设置对应权重
model_weighted <- svm(rating ~ ., 
                      data = train_scaled_df,
                      kernel = "radial",
                      gamma = tune_result$best.parameters$gamma,
                      cost = tune_result$best.parameters$cost,
                      class.weights = c("1" = 2, "2" = 1, "3" = 2))
  • 换用更鲁棒的评估指标:调参时不要只依赖准确率,可以手动实现分层交叉验证,计算F1分数、AUC等对类别不平衡更友好的指标,再选择最优参数。

4. 检查模型状态

训练后查看模型的支持向量数量,判断是否过拟合/欠拟合:

summary(model_weighted)

如果支持向量数量接近训练集样本数,说明过拟合;如果过少,说明欠拟合,需要调整参数范围。

5. 尝试其他核函数

如果径向基核效果一直不好,可以试试线性核或多项式核,看看是否更适配你的数据:

# 线性核调参示例
tune_linear <- tune.svm(rating ~ ., 
                        data = train_scaled_df,
                        kernel = "linear",
                        cost = 10^c(-2, -1, 0, 1, 2),
                        cross = 10,
                        sampling = "stratified")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:25:03