使用h2o::h2o.glrm()处理混合数据时遇错误求排查
H2O GLRM混合类型变量降维报错排查与修正
需求说明
使用H2O的h2o.glrm()对包含二元变量(两水平因子)、多水平名义因子、多水平有序因子的混合数据集降维,对应损失函数分别为Logistic、Categorical、Ordinal。
原始代码与报错
初始代码(全因子数据集)
# Load packages library(tibble) library(h2o) # Example data for MRE my_data <- tibble::tibble( var.1 = as.factor(rep(1, 10)), var.2 = as.factor(c(NA, 1, 1, -1, -1, -1, 1, 1, 1, 1)), var.3 = as.factor(rep(-1, 10)), var.4 = as.factor(c(-1, 1, 1, 1, 1, 1, -1, 1, 1, 1)), var.5 = as.factor(rep(-1, 10)), var.6 = as.factor(c(1, 2, 3, 1, 2, 2, 2, 2, 2, 3)), var.7 = as.factor(c(NA, 2, 3, 2, 2, 2, 2, 3, 1, 2)), var.8 = as.factor(c(2, 3, 2, 2, 2, 2, 3, 2, 2, 2)), var.9 = as.factor(c(1, 2, 3, 4, 1, 2, 3, 4, 1, 3)), var.10 = as.factor(c(1, 1, 1, 1, NA, 1, 1, -1, -1, 1)) ) my_data_types <- tibble::tibble( var_name = paste("var", 1:10, sep = "."), var_type = c(rep("binary", 5), rep("ordinal", 3), "nominal", "binary") ) # Initialize h2o cluster h2o::h2o.init() h2o::h2o.no_progress() # Convert data to h2o object my_data_h2o <- h2o::as.h2o(my_data) # Define loss function for ordinal and nominal variables losses <- tibble::tibble( index = which(my_data_types$var_type %in% c("ordinal", "nominal")) - 1, loss = NA_character_ ) for (i in seq_along(losses$index)) { losses$loss[i] <- ifelse(my_data_types$var_type[losses$index[i] + 1] == "ordinal", "Ordinal", ifelse(my_data_types$var_type[losses$index[i] + 1] == "nominal", "Categorical", NA)) } # Run GLRM my_glrm <- h2o::h2o.glrm( training_frame = my_data_h2o, k = 2, loss = "Logistic", loss_by_col_idx = losses$index, loss_by_col = losses$loss, regularization_x = "None", regularization_y = "None", transform = "NONE", max_iterations = 2000, seed = 12345 )
初始报错
Error in .h2o.doSafeREST(h2oRestApiVersion = h2oRestApiVersion, urlSuffix = page, : ERROR MESSAGE: Illegal argument(s) for GLRM model: GLRM_model_R_1683532209346_20. Details: ERRR on field: _loss: Logistic is not a numeric loss function
替代代码(二元变量转数值)
# Alternative example data for MRE my_data_2 <- tibble::tibble( var.1 = rep(1, 10), var.2 = c(NA, 1, 1, -1, -1, -1, 1, 1, 1, 1), var.3 = rep(-1, 10), var.4 = c(-1, 1, 1, 1, 1, 1, -1, 1, 1, 1), var.5 = rep(-1, 10), var.6 = as.factor(c(1, 2, 3, 1, 2, 2, 2, 2, 2, 3)), var.7 = as.factor(c(NA, 2, 3, 2, 2, 2, 2, 3, 1, 2)), var.8 = as.factor(c(2, 3, 2, 2, 2, 2, 3, 2, 2, 2)), var.9 = as.factor(c(1, 2, 3, 4, 1, 2, 3, 4, 1, 3)), var.10 = c(1, 1, 1, 1, NA, 1, 1, -1, -1, 1) ) # Convert data to h2o object my_data_2_h2o <- h2o::as.h2o(my_data_2) # Run GLRM my_glrm_2 <- h2o::h2o.glrm( training_frame = my_data_2_h2o, k = 2, loss = "Logistic", loss_by_col_idx = losses$index, loss_by_col = losses$loss, regularization_x = "None", regularization_y = "None", transform = "NONE", max_iterations = 2000, seed = 12345 )
替代代码报错
Error in .h2o.doSafeREST(h2oRestApiVersion = h2oRestApiVersion, urlSuffix = page, : ERROR MESSAGE: Illegal argument(s) for GLRM model: GLRM_model_R_1683532209346_21. Details: ERRR on field: _loss: Logistic is not a numeric loss function ERRR on field: _loss_by_col: Loss function Logistic cannot be applied to numeric column 0 ERRR on field: _loss_by_col: Loss function Logistic cannot be applied to numeric column 1 ERRR on field: _loss_by_col: Loss function Logistic cannot be applied to numeric column 6
错误原因
- 全局损失参数错误:
loss参数是所有未通过loss_by_col指定损失的列的默认损失,H2O要求该参数必须是数值型损失函数(如Quadratic),而Logistic属于分类损失,不能作为全局默认。 - 损失函数与列类型不匹配:
- Logistic损失仅适用于二分类因子列,不能用于数值列,将二元变量转成数值后,无法应用Logistic损失。
- 初始代码中仅给有序、名义列指定了损失,二元列使用全局的Logistic损失,但全局损失不允许用分类损失,导致冲突。
修正方案
- 全局默认损失
loss设置为数值型损失(如"Quadratic")。 - 所有分类列(二元、有序、名义)都通过
loss_by_col_idx和loss_by_col指定对应损失,确保每类变量匹配正确的损失函数:- 二元因子列:
"Logistic" - 有序因子列:
"Ordinal" - 多水平名义因子列:
"Categorical"
- 二元因子列:
- 二元变量保留为因子类型,确保H2O识别为二分类列,适配Logistic损失。
修正后可运行代码
library(tibble) library(h2o) library(dplyr) # 初始化H2O集群 h2o.init() h2o.no_progress() # 构造混合类型数据集 my_data <- tibble( var.1 = as.factor(rep(1, 10)), var.2 = as.factor(c(NA, 1, 1, -1, -1, -1, 1, 1, 1, 1)), var.3 = as.factor(rep(-1, 10)), var.4 = as.factor(c(-1, 1, 1, 1, 1, 1, -1, 1, 1, 1)), var.5 = as.factor(rep(-1, 10)), var.6 = as.factor(c(1, 2, 3, 1, 2, 2, 2, 2, 2, 3)), var.7 = as.factor(c(NA, 2, 3, 2, 2, 2, 2, 3, 1, 2)), var.8 = as.factor(c(2, 3, 2, 2, 2, 2, 3, 2, 2, 2)), var.9 = as.factor(c(1, 2, 3, 4, 1, 2, 3, 4, 1, 3)), var.10 = as.factor(c(1, 1, 1, 1, NA, 1, 1, -1, -1, 1)) ) # 定义变量类型映射 my_data_types <- tibble( var_name = paste("var", 1:10, sep = "."), var_type = c(rep("binary", 5), rep("ordinal", 3), "nominal", "binary") ) # 转换为H2O对象 my_data_h2o <- as.h2o(my_data) # 为所有列映射对应损失函数 loss_mapping <- case_when( my_data_types$var_type == "binary" ~ "Logistic", my_data_types$var_type == "ordinal" ~ "Ordinal", my_data_types$var_type == "nominal" ~ "Categorical" ) # 提取列索引(H2O列索引从0开始) col_indices <- seq_along(loss_mapping) - 1 # 运行GLRM my_glrm <- h2o.glrm( training_frame = my_data_h2o, k = 2, loss = "Quadratic", # 全局默认数值损失 loss_by_col_idx = col_indices, loss_by_col = loss_mapping, regularization_x = "None", regularization_y = "None", transform = "NONE", max_iterations = 2000, seed = 12345 ) # 查看降维结果 head(h2o.predict(my_glrm, my_data_h2o))
内容的提问来源于stack exchange,提问作者Dan
相关产品推荐
相关产品推荐

