R中调用XGBoost报错:标签长度与输入数据行数不匹配
R环境XGBoost建模标签长度不匹配报错排查
问题场景
首次在R环境中使用XGBoost搭建模型,目的是对比不同数据科学技术的建模效果。本次使用的数据集为数年前构建评分卡/PD(违约概率)模型时的留存数据集,用于验证XGBoost在该数据集上的表现。
初始运行代码如下:
keeps1 <- c("gb_estassval_woe","gb_prof_occ_woe","biztype_woe", "gb_educ_woe", "gb_region_woe", "gb_resstat_woe", "gb_leg_tel_woe", "gb_age_woe", "gb_TimeJob_woe", "gb_gender_woe", "gb_marstat_woe", "gb") cc_dev1a <-subset(cc_dev_fin,,keeps1) sparse_matrix <- sparse.model.matrix(gb ~ ., data =cc_dev1a)[,-1] #gb为1/0二分类目标变量 output_vector = cc_dev1a[,gb ] == "Marked" str(cc_dev1a) str(sparse_matrix) str(output_vector) head(output_vector) #校验记录数:output_vector共57483条,sparse_matrix共57157行 #初步猜测行数减少由缺失值导致,但未检测到NA(所有变量均已预处理为证据权重WOE整数值) bst <- xgboost(data = sparse_matrix, label = output_vector, max_depth = 4, eta = 1, nthread = 2, nrounds = 10,objective = "binary:logistic")
报错信息
Error in setinfo.xgb.DMatrix(dmat, names(p), p[[1]]) : The length of labels must equal to the number of rows in the input data
初步排查结果
- 标签向量
output_vector共57483条记录,生成的稀疏矩阵sparse_matrix仅57157行,二者长度不匹配是直接报错原因 - 初步猜测行数差异由缺失值导致,但常规NA检测未发现异常:所有变量均已预处理为证据权重(Weight of Evidence, WOE)整数值,未检测到NA值
根因说明
sparse.model.matrix()默认的缺失值处理规则为na.action = na.omit,会自动剔除所有包含特殊异常值的行,这类异常值包括NaN、Inf、因子变量未定义的空水平,普通is.na()检测无法覆盖全部这类值,因此会出现“没检测到NA但行数减少”的现象。- 标签向量直接从未做行剔除的原始数据集提取,没有和稀疏矩阵的保留行做对齐,最终出现长度不匹配。
- 初始代码存在两处不规范写法,会放大错位风险:一是
subset函数多写了一个逗号,未显式声明选择列的参数;二是提取gb列时未给列名加引号,容易被环境中同名变量干扰导致取值错误。
可行解决方案
方案1:关闭自动删行,依托XGBoost原生能力处理缺失值
XGBoost原生支持缺失值自动分裂优化,不需要提前手动删除含缺失的样本,调整sparse.model.matrix的缺失值处理参数保留所有行,同时规范列索引写法,训练前增加行数校验即可:
keeps1 <- c("gb_estassval_woe","gb_prof_occ_woe","biztype_woe", "gb_educ_woe", "gb_region_woe", "gb_resstat_woe", "gb_leg_tel_woe", "gb_age_woe", "gb_TimeJob_woe", "gb_gender_woe", "gb_marstat_woe", "gb") cc_dev1a <- subset(cc_dev_fin, select = keeps1) # 设定na.action = na.pass,禁止函数自动剔除样本行 sparse_matrix <- sparse.model.matrix(gb ~ ., data = cc_dev1a, na.action = na.pass)[,-1] # 列名加引号规范索引,标签转成0/1数值型适配XGBoost要求 output_vector <- as.numeric(cc_dev1a[, "gb"] == "Marked") # 训练前强制校验行数一致性 stopifnot(nrow(sparse_matrix) == length(output_vector)) bst <- xgboost( data = sparse_matrix, label = output_vector, max_depth = 4, eta = 1, nthread = 2, nrounds = 10, objective = "binary:logistic" )
方案2:行ID对齐,同步剔除异常样本
如果需要保留sparse.model.matrix的自动剔除逻辑,可通过行ID匹配的方式,同步从标签向量中剔除对应被删的样本,避免行错位:
keeps1 <- c("gb_estassval_woe","gb_prof_occ_woe","biztype_woe", "gb_educ_woe", "gb_region_woe", "gb_resstat_woe", "gb_leg_tel_woe", "gb_age_woe", "gb_TimeJob_woe", "gb_gender_woe", "gb_marstat_woe", "gb") cc_dev1a <- subset(cc_dev_fin, select = keeps1) # 给原始数据集增加唯一行ID cc_dev1a$tmp_row_id <- seq_len(nrow(cc_dev1a)) sparse_matrix <- sparse.model.matrix(gb ~ . - tmp_row_id, data = cc_dev1a)[,-1] # 提取稀疏矩阵保留的行ID keep_rows <- as.numeric(rownames(sparse_matrix)) # 按保留的行ID提取对应标签 output_vector <- as.numeric(cc_dev1a[keep_rows, "gb"] == "Marked")
额外排查项
如果调整后仍存在行数差异,运行以下代码全量检测非NA类的特殊异常值:
# 检测每列的NaN、Inf值数量 sapply(cc_dev1a, function(col) sum(is.nan(col) | is.infinite(col))) # 检测因子列是否存在空字符串水平 sapply(cc_dev1a, function(col) if(is.factor(col)) sum(col == "") else 0)
内容的提问来源于stack exchange,提问作者Matthew Freeman
相关产品推荐
相关产品推荐

