R语言随机森林调参报错及自动寻优实现咨询
作物分类模型问题分析与解决
问题背景
拥有如下作物分类数据集:
mydata=structure(list(crop_name = c("Guar", "Guar", "Guar", "Guar", "Guar", "Guar", "Guar", "Guar", "Guar", "Guar", "Bajra", "Bajra", "Bajra", "Bajra", "Bajra", "Bajra", "Bajra", "Bajra", "Bajra", "Bajra"), B08A = c(2781L, 2817L, 2700L, 1780L, 3702L, 4094L, 3921L, 3780L, 2855L, 3501L, 2963L, 2578L, 1996L, 4502L, 4217L, 3528L, 3689L, 3529L, 3050L, 2996L), nir = c(2576L, 2607L, 2328L, 1541L, 3329L, 3681L, 3636L, 3382L, 2481L, 3174L, 2820L, 2691L, 2318L, 4229L, 3868L, 3648L, 3271L, 3244L, 2497L, 2752L), swir = c(2866L, 3589L, 2782L, 1447L, 2784L, 3084L, 3019L, 2972L, 1779L, 2687L, 3889L, 2332L, 1570L, 2574L, 2910L, 2546L, 2953L, 3176L, 3198L, 3464L), gcvi = c(0.624211853, 1.065768621, 0.897310513, 0.861111111, 1.384670487, 2.349408553, 2.246428571, 1.756316218, 1.753607103, 2.933085501, 0.923601637, 0.996290801, 2.274011299, 2.311667971, 3.084477296, 2.86031746, 2.494658119, 2.164878048, 1.824660633, 1.596226415)), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -20L))
需求:构建分类器预测作物类别(Bajra和Guar),自动枚举随机森林超参数,使模型F-measure达到至少90%;若无法达到则返回最高精度。
编写的代码如下:
library(caret) library(randomForest) # Convert the factor variable to a numeric one mydata$crop_name <- as.numeric(mydata$crop_name) - 1 # We split the data into training and test samples set.seed(123) trainIndex <- createDataPartition(mydata$crop_name, p = 0.8, list = FALSE) trainData <- mydata[trainIndex, ] testData <- mydata[-trainIndex, ] # Define a function to evaluate the model evaluate_model <- function(model, testData) { predictions <- predict(model, testData) confusionMatrix <- confusionMatrix(data = factor(predictions, levels = c(0, 1)), reference = factor(testData$crop_name, levels = c(0, 1)), positive = "1") precision <- confusionMatrix$byClass['Pos Pred Value'] recall <- confusionMatrix$byClass['Sensitivity'] f1 <- 2 * precision * recall / (precision + recall) return(list(precision = precision, recall = recall, f1 = f1)) } # **Random Forest** # Define a grid of parameters for searching rfGrid <- expand.grid(mtry = c(2, 3, 4), ntree = c(500, 1000, 1500)) best_rf_f1 <- 0 # Enumerate random forest parameters for (i in 1:nrow(rfGrid)) { # Model training rfModel <- randomForest(crop_name ~ ., data = trainData, mtry = rfGrid$mtry[i], ntree = rfGrid$ntree[i]) # Model evaluation rfMetrics <- evaluate_model(rfModel, testData) # Save the model if the F1-measure is better than the previous ones if (rfMetrics$f1 > best_rf_f1) { best_rf_f1 <- rfMetrics$f1 best_rf_model <- rfModel } } cat("Random Forest - F1-measure:", best_rf_f1, "\n")
运行时出现错误及警告:
Error in if (rfMetrics$f1 > best_rf_f1) { : missing value where TRUE/FALSE needed In addition: Warning message: In randomForest.default(m, y, ...) : The response has five or fewer unique values. Are you sure you want to do regression?
错误原因分析
- 回归任务误判:将
crop_name转成数值后,randomForest默认将其视为连续变量,执行回归任务而非分类任务。回归模型的预测结果是连续数值,后续转换为因子时会出现不匹配,导致confusionMatrix计算失败,f1值变为NA,引发判断条件的错误。 - 因变量类型错误:分类任务要求因变量是因子类型,数值类型会触发回归模式,这就是警告信息的来源。
修正后的代码
library(caret) library(randomForest) # 保留因变量的因子类型(核心修正:不转成数值,或转后再转回因子) mydata$crop_name <- factor(mydata$crop_name, levels = c("Guar", "Bajra")) # 划分训练集和测试集 set.seed(123) trainIndex <- createDataPartition(mydata$crop_name, p = 0.8, list = FALSE) trainData <- mydata[trainIndex, ] testData <- mydata[-trainIndex, ] # 模型评估函数(适配分类任务的预测结果) evaluate_model <- function(model, testData) { predictions <- predict(model, testData, type = "class") confusionMatrix <- confusionMatrix(data = predictions, reference = testData$crop_name, positive = "Bajra") # 明确正类别 precision <- confusionMatrix$byClass['Pos Pred Value'] recall <- confusionMatrix$byClass['Sensitivity'] f1 <- 2 * precision * recall / (precision + recall) return(list(precision = precision, recall = recall, f1 = f1)) } # 定义超参数网格 rfGrid <- expand.grid(mtry = c(2, 3, 4), ntree = c(500, 1000, 1500)) best_rf_f1 <- 0 target_f1 <- 0.9 # 目标F1阈值 # 超参数迭代搜索 for (i in 1:nrow(rfGrid)) { # 训练分类随机森林模型 rfModel <- randomForest(crop_name ~ ., data = trainData, mtry = rfGrid$mtry[i], ntree = rfGrid$ntree[i], importance = TRUE) # 评估模型 rfMetrics <- evaluate_model(rfModel, testData) # 更新最优模型 if (rfMetrics$f1 > best_rf_f1) { best_rf_f1 <- rfMetrics$f1 best_rf_model <- rfModel best_params <- rfGrid[i, ] # 达到目标精度则提前终止 if (best_rf_f1 >= target_f1) { cat("达到目标F1值,提前终止搜索\n") break } } } # 输出结果 cat("最优随机森林模型 - F1值:", best_rf_f1, "\n") cat("最优超参数: mtry =", best_params$mtry, ", ntree =", best_params$ntree, "\n")
关键修正说明
- 因变量类型修正:将
crop_name设置为因子类型,确保randomForest执行分类任务,避免回归模式的误判。 - 评估函数适配:分类模型的预测结果是因子,无需额外转换,直接传入
confusionMatrix,同时明确正类别(如"Bajra")。 - 提前终止逻辑:增加目标F1阈值判断,一旦达到90%则停止超参数搜索,提升效率。
- 参数记录:保存最优超参数,方便后续复现。
内容的提问来源于stack exchange,提问作者psysky
相关产品推荐
相关产品推荐

