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

如何在训练-测试场景中有效应用调优后的SVM模型

解决训练-测试场景下调优SVM失效的问题

这问题太典型了——全数据集上模型表现得倍儿棒,但一拆分训练测试集就拉胯,甚至直接躺平全预测成多数类,核心问题出在数据拆分逻辑、类别权重的计算时机和调优流程的合理性上,咱们一步步来解决:

1. 先搞清楚为啥拆分后效果崩了

你最后测试集的混淆矩阵显示,模型把所有样本都预测成了9类,这大概率是两个原因:

  • 首先检查你的createDataPartition是否真的做了分层抽样:虽然函数默认是分层,但如果你的少数类(-1、0)样本数太少,抽样后训练集里的这些类可能还是少得可怜,模型根本学不会识别它们的特征。
  • 其次,你用的class.weights是基于全数据集的样本占比计算的,但训练集的类别分布和全数据集肯定不一样,用错权重等于给模型指了歪路,自然学偏了。

先验证下训练集和测试集的类别分布:

train_index <- createDataPartition(dtm$type, p=0.75, list=FALSE, strata=dtm$type)
train <- dtm[train_index,]
test <- dtm[-train_index,]

# 查看分布
prop.table(table(train$type))
prop.table(table(test$type))

如果训练集里-1、0类的占比和全数据集偏差很大,那第一步就要把抽样逻辑掰正。

2. 修正类别权重的计算方式

类别权重的核心是给少数类更高的权重,但这个权重必须基于当前训练集的分布计算,绝对不能用全数据集的!

正确的计算逻辑(两种常用方式任选):

# 基于训练集计算类别权重
train_class_counts <- table(train$type)

# 方式1:1/该类在训练集的占比(简单直接)
class_weights <- setNames(1 / prop.table(train_class_counts), names(train_class_counts))

# 方式2:总样本数/(类别数*该类样本数)(更均衡的加权方式)
class_weights <- setNames(nrow(train)/(length(levels(train$type)) * train_class_counts), names(train_class_counts))

这样计算出来的权重才是适配训练集的,能真正帮模型重视少数类。

3. 重新走正确的调优流程

你之前的tune是直接用全数据集做的,这属于数据泄露——调优过程用到了测试集的信息,所以全数据集上效果好,但放到真实训练测试场景就失效了。正确的流程应该是:

# 1. 先分层拆分训练/测试集,锁死测试集不动
train_index <- createDataPartition(dtm$type, p=0.75, list=FALSE, strata=dtm$type)
train <- dtm[train_index,]
test <- dtm[-train_index,]

x_train <- subset(train, select=-type)
y_train <- train$type

# 2. 基于训练集计算类别权重
train_class_counts <- table(y_train)
class_weights <- setNames(nrow(train)/(4 * train_class_counts), names(train_class_counts))

# 3. 仅在训练集上做交叉验证调优(绝对不能碰测试集)
svm_tune <- tune(svm, 
                 train.x=x_train, 
                 train.y=y_train, 
                 class.weights = class_weights,
                 ranges=list(cost=10^(-1:2), gamma=c(.25, .5, 1)), # 可以根据需要调整搜索范围
                 tunecontrol = tune.control(cross=10)) # 10折交叉验证找最佳参数

# 4. 用最佳参数在整个训练集上训练模型
best_svm <- svm(type ~ ., 
                data=train, 
                cost=svm_tune$best.parameters$cost, 
                gamma=svm_tune$best.parameters$gamma, 
                class.weights = class_weights)

# 5. 最后用测试集评估真实性能
pred_test <- predict(best_svm, newdata=test)
confusionMatrix(pred_test, test$type)

4. 针对极端不平衡数据的额外优化

你的数据里9类占了78%,-1和0类占比极低(2.5%和0.5%),仅靠权重可能不够,试试这些方法:

  • 过采样少数类:用SMOTE算法生成少数类的合成样本,比如DMwR包的SMOTE函数,让训练集的类别分布更均衡。
  • 换用更合理的评估指标:准确率在不平衡数据里毫无意义,重点看少数类的召回率(比如-1类有多少被正确识别)、F1分数或者ROC-AUC,这些指标才能反映模型的真实性能。
  • 尝试线性核SVM:你的特征是文本DTM(高维稀疏),线性核在这种场景下往往比径向基核效果更好,计算也更快,可以把kernel="linear"加入调优范围试试。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:20:15