R语言predict()函数基于J48模型预测结果异常求助
R中C4.5模型预测结果异常问题排查
问题现象
使用RWeka的J48(C4.5决策树)模型训练高尔夫打球决策数据时,训练集中所有Nublado(阴天)场景对应的Jugar(是否打球)结果均为Si(是),但输入Panorama=Nublado, Temperatura=Medio, Humedad=Normal, Viento=Normal时,predict()函数返回错误结果No(否),预期结果应为Si。
相关代码
library(RWeka) library(caret) library(datasets) table_golf = read.table("C:/Users/Mario S-Herrero/Desktop/golf.txt.txt", header = T, sep = ",", ) data_golf <- as.data.frame(table_golf) data_golf$Panorama=as.factor(data_golf$Panorama) data_golf$Temperatura=as.factor(data_golf$Temperatura) data_golf$Humedad=as.factor(data_golf$Humedad) data_golf$Viento=as.factor(data_golf$Viento) data_golf$Jugar=as.factor(data_golf$Jugar) modelC45 <- J48(`Jugar` ~ ., data = data_golf) modelC45 plot(modelC45) # 创建输入数据并预测 nuevopartido = read.table("C:/Users/Mario S-Herrero/Desktop/input.txt", header = T, sep = ",", ) input <- as.data.frame(nuevopartido) input$Panorama=as.factor(input$Panorama) input$Temperatura=as.factor(input$Temperatura) input$Humedad=as.factor(input$Humedad) input$Viento=as.factor(input$Viento) prediccion <- predict(modelC45,input) plot(prediccion)
训练数据(golf.txt)
Panorama,Temperatura,Humedad,Viento,Jugar Soleado,Calor,Alta,Ligero,No Soleado,Calor,Alta,Fuerte,No Nublado,Calor,Alta,Ligero,Si Lluvia,Medio,Alta,Ligero,Si Lluvia,Frio,Normal,Ligero,Si Lluvia,Frio,Normal,Fuerte,No Nublado,Frio,Normal,Fuerte,Si Soleado,Medio,Alta,Ligero,No Soleado,Medio,Normal,Ligero,Si Lluvia,Medio,Normal,Ligero,Si Soleado,Medio,Normal,Fuerte,Si Nublado,Medio,Alta,Fuerte,Si Nublado,Calor,Normal,Ligero,Si Lluvia,Medio,Alta,Fuerte,No
输入数据(input.txt)
Panorama,Temperatura,Humedad,Viento Nublado,Medio,Normal,Normal
问题原因
核心问题出在输入数据的Viento字段包含训练数据中不存在的因子水平:
- 训练数据里
Viento的取值只有Ligero(微风)和Fuerte(大风)两个水平; - 输入数据的
Viento是Normal,这个水平从未在训练集中出现过。
当J48模型遇到训练时未见过的因子水平时,无法按照决策树的分支逻辑进行判断,会默认将样本归类到某个类别(此处错误归为No),导致预测结果不符合预期。
解决方案
方案1:修正输入数据(最直接)
如果是输入错误,将input.txt中的Viento值改为训练数据中存在的Ligero或Fuerte,比如:
Panorama,Temperatura,Humedad,Viento Nublado,Medio,Normal,Ligero
此时重新运行预测,会得到预期的Si结果。
方案2:提前定义所有可能的因子水平(适用于业务存在新水平的场景)
如果业务中确实存在Normal这个风速水平,需要在转换因子时明确指定所有可能的水平,确保训练和输入数据的因子水平一致:
# 训练数据转换因子时指定全量水平 data_golf$Viento <- factor(data_golf$Viento, levels = c("Ligero", "Fuerte", "Normal")) # 输入数据同步使用相同的水平定义 input$Viento <- factor(input$Viento, levels = c("Ligero", "Fuerte", "Normal"))
注:由于训练数据中没有Normal的样本,模型仍无法对该水平的样本做出准确预测,但可以避免因未知水平导致的异常归类。若要准确预测,需补充包含Viento=Normal的训练样本后重新训练模型。
内容的提问来源于stack exchange,提问作者Spike Vinalyan
相关产品推荐
相关产品推荐

