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

SMOTE平衡数据集后LightGBM训练仅单类问题修复请求

解决SMOTE后LightGBM提示仅单类样本的问题

问题背景

原数据集为二分类不平衡数据集,Target变量中类别"0"有61471条记录,类别"1"有4456条记录。为缓解不平衡,使用SMOTE对训练集进行过采样处理。

SMOTE处理情况

执行SMOTE代码

trainSMOTE <- SMOTE(target ~ ., train, perc.over = 400, k = 5)
dim(trainSMOTE)

输出结果:57928 67

平衡验证

table(trainSMOTE$target)

输出结果:

0     1 
35648 22280

可见SMOTE后数据集已达到平衡状态。

LightGBM训练异常情况

训练代码片段

创建LightGBM数据集

train_data <- lgb.Dataset(data.matrix(trainSMOTE[, -9]), label = trainSMOTE[, trainSMOTE$target])
test_data <- lgb.Dataset(data.matrix(test[, -9]), label = test[, test$target])

模型参数定义

params <- list(
  objective = "binary",
  metric = 'auc', 
  boosting_type = "gbdt",
  num_leaves = 100, 
  learning_rate = 0.05,
  feature_fraction = 0.9,
  bagging_fraction = 0.8,
  bagging_freq = 5,
  min_data_in_leaf = 50,
  max_depth = -1,
  verbose = -1
)

启动训练

model <- lgb.train(params = params,
                   data = train_data,
                   valids = list(test = test_data),
                   early_stopping_rounds = 50)

模型报错信息

[LightGBM] [Warning] Contains only one class[LightGBM].
[Info] Number of positive: 57928, number of negative: 0.
[LightGBM] [Warning] Auto-choosing col-wise multi-threading, the overhead of testing was 0.050367 seconds.
You can set force_col_wise=true to remove the overhead.
[LightGBM] [Info] Total Bins 15250.
[LightGBM] [Info] Number of data points in the train set: 57928, number of used features: 65.
[LightGBM] [Info] [binary:BoostFromScore]: pavg=1.000000 -> initscore=34.539576.
[LightGBM] [Info] Start training from score 34.539576.
[LightGBM] [Info] [binary:BoostFromScore]: pavg=1.000000 -> initscore=34.539576.
[LightGBM] [Warning] Stopped training because there are no more leaves that meet the split requirements.
[1] "[1]: test's auc:0.5"...........

问题原因

核心错误出在标签列的提取逻辑:
代码中label = trainSMOTE[, trainSMOTE$target]的写法完全错误,trainSMOTE$target是一个长度为57928的向量,用它作为列索引时,会对每一行提取对应索引的列值,最终得到的不是标签列,而是一个混乱的矩阵,导致LightGBM识别到的所有样本标签被错误统一为同一类。

解决方案

修正标签提取逻辑

将标签列的提取方式改为直接取目标列,以下两种方式均可:

方式1:按列名提取(更健壮,避免列索引变化)

# 训练集
train_data <- lgb.Dataset(
  data = data.matrix(trainSMOTE[, -which(names(trainSMOTE) == "target")]),
  label = trainSMOTE$target
)
# 测试集
test_data <- lgb.Dataset(
  data = data.matrix(test[, -which(names(test) == "target")]),
  label = test$target
)

方式2:按列索引提取(已知target是第9列时使用)

# 训练集
train_data <- lgb.Dataset(
  data = data.matrix(trainSMOTE[, -9]),
  label = trainSMOTE[, 9]
)
# 测试集
test_data <- lgb.Dataset(
  data = data.matrix(test[, -9]),
  label = test[, 9]
)

额外验证步骤

在创建数据集前,先确认标签分布是否正确,避免再次出错:

# 确认训练集标签分布
table(trainSMOTE$target)
# 确认提取的label是否与原标签一致
table(trainSMOTE[, 9]) # 对应方式2的列索引

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 19:53:10