python r loops prediction h2o

python - Cálculo de MAPE en H2o: Error: el tipo de columna provisto POSIXct es desconocido



loops prediction (3)

Siguiendo mi pregunta respondida: R o Python - haga un bucle con los datos de la prueba - Validación de la predicción las próximas 24 horas (96 valores cada día)

Quiero predecir el día siguiente utilizando el paquete H2o. Puede encontrar una explicación detallada de mi conjunto de datos en el mismo enlace anterior .

La dimensión de datos en H2o es diferente.

Entonces, después de hacer la predicción, quiero calcular el MAPE

Tengo que cambiar los datos de entrenamiento y pruebas al formato H2o

train_h2o <- as.h2o(train_data) test_h2o <- as.h2o(test_data) mape_calc <- function(sub_df) { pred <- predict.glm(glm_model, sub_df) actual <- sub_df$Ptot mape <- 100 * mean(abs((actual - pred)/actual)) new_df <- data.frame(date = sub_df$date[[1]], mape = mape) return(new_df) } # LIST OF ONE-ROW DATAFRAMES df_list <- by(test_data, test_data$date, map_calc) # FINAL DATAFRAME final_df <- do.call(rbind, df_list)

El código superior funciona bien para la validación de predicción " No H2O " para el día siguiente y calcula el MAPE para cada día.

Intenté convertir el modelo predicho H2o al formato normal, pero de acuerdo con: https://stackoverflow.com/a/39221269/9341589 , no es posible.

Para hacer una predicción en H2O:

por ejemplo, digamos que queremos crear un modelo de bosque aleatorio

y <- "RealPtot" #target x <- names(train_h2o) %>% setdiff(y) #features rforest.model <- h2o.randomForest(y=y, x=x, training_frame = train_h2o, ntrees = 2000, mtries = 3, max_depth = 4, seed = 1122)

Luego podemos obtener la predicción para el conjunto de datos completo como se muestra a continuación.

predict.rforest <- as.data.frame(h2o.predict(rforest.model, test_h2o)

Pero en mi caso estoy tratando de obtener una predicción de un día utilizando mape_calc

NOTA: Cualquier pensamiento en R o Python será apreciado.

ACTUALIZACIÓN2 (ejemplo reproducible ): ** Siguiendo los pasos de @Darren Cook:

Proporcioné un ejemplo más simple: conjunto de datos de viviendas de Boston.

library(tidyverse) library(h2o) h2o.init(ip="localhost",port=54322,max_mem_size = "128g") data(Boston, package = "MASS") names(Boston) [1] "crim" "zn" "indus" "chas" "nox" "rm" "age" "dis" "rad" "tax" "ptratio" [12] "black" "lstat" "medv" set.seed(4984) #Added 15 minute Time and date interval Boston$date<- seq(as.POSIXct("01-09-2017 03:00", format = "%d-%m-%Y %H:%M",tz=""), by = "15 min", length = 506) #select first 333 values to be trained and the rest to be test data train = Boston[1:333,] test = Boston[334:506,] #Dropped the date and time train_data_finialized <- subset(train, select=-c(date)) test_data_finialized <- test #Converted the dataset to h2o object. train_h2o<- as.h2o(train_data_finialized) #test_h2o<- as.h2o(test) #Select the target and feature variables for h2o model y <- "medv" #target x <- names(train_data_finialized) %>% setdiff(y) #feature variables # Number of CV folds (to generate level-one data for stacking) nfolds <- 5 #Replaced RF model by GBM because GBM run faster # Train & Cross-validate a GBM my_gbm <- h2o.gbm(x = x, y = y, training_frame = train_h2o, nfolds = nfolds, fold_assignment = "Modulo", keep_cross_validation_predictions = TRUE, seed = 1) mape_calc <- function(sub_df) { p <- h2o.predict(my_gbm, as.h2o(sub_df)) pred <- as.vector(p) actual <- sub_df$medv mape <- 100 * mean(abs((actual - pred)/actual)) new_df <- data.frame(date = sub_df$date[[1]], mape = mape) return(new_df) } # LIST OF ONE-ROW DATAFRAMES df_list <- by(test_data_finialized, test_data_finialized$date, mape_calc) final_df <- do.call(rbind, df_list)

Este es el error que estoy recibiendo ahora:

Error en .h2o.doSafeREST (h2oRestApiVersion = h2oRestApiVersion, urlSuffix = page,:

MENSAJE DE ERROR:

El tipo de columna proporcionado POSIXct es desconocido. No se puede continuar con el análisis debido a un argumento no válido.


¿Podría simplemente ser el formato de archivo que es el problema? Obtuve "el tipo de columna provisto POSIXct es desconocido" después de importar desde Excel y ejecutar:

hr_data_h2o <- as.h2o(hr_data) split_h2o <- h2o.splitFrame(hr_data_h2o, c(0.7, 0.15), seed = 1234)

Cambié el archivo de origen a una pestaña delimitada (sin otros cambios) y el problema desapareció.


H2O se ejecuta en un proceso separado a R (ya sea que H2O esté en el servidor local o en un centro de datos distante). Los datos de H2O y los modelos de H2O se mantienen en ese proceso de H2O y no pueden ser vistos por R.

Lo que dH <- as.h2o(dR) hace es copiar un cuadro de datos R, dR , en el espacio de memoria del H2O. El dH es entonces una variable R que describe el marco de datos H2O. Es decir, es un puntero, o una manija; No es el dato en sí.

Lo que dR <- as.data.frame(dH) hace es copiar los datos de la memoria del proceso H2O en la memoria del proceso R. ( as.vector(dH) hace lo mismo para cuando dH describe una sola columna)

Entonces, la forma más sencilla de modificar su mape_calc() , suponiendo que sub_df es un marco de datos R, es cambiar las primeras dos líneas de la siguiente manera:

mape_calc <- function(sub_df) { p <- h2o.predict(rforest.model, as.h2o(sub_df)) pred <- as.vector(p) actual <- sub_df$Ptot mape <- 100 * mean(abs((actual - pred)/actual)) new_df <- data.frame(date = sub_df$date[[1]], mape = mape) return(new_df) }

Es decir, subir sub_df a H2O y dárselo a h2o.predict() . Luego use as.vector() para descargar la predicción que se hizo.

Esto fue relativo a su código original. Así que mantén la versión original de esto:

# LIST OF ONE-ROW DATAFRAMES df_list <- by(test_data, test_data$date, map_calc)

No uso by() directamente en test_h2o .

ACTUALIZACIÓN basada en la pregunta editada:

Hice dos cambios a su código de ejemplo. Primero, quité la columna de fecha de sub_df . Eso fue lo que estaba causando el mensaje de error.

El segundo cambio fue simplemente para simplificar el tipo de retorno; no es importante, pero terminó con la columna de fecha duplicada, antes.

mape_calc <- function(sub_df) { sub_df_minus_date <- subset(sub_df, select=-c(date)) p <- h2o.predict(my_gbm, as.h2o(sub_df_minus_date)) pred <- as.vector(p) actual <- sub_df$medv mape <- 100 * mean(abs((actual - pred)/actual)) data.frame(mape = mape) }

ASIDE: h2o.predict() es más eficiente cuando se trabaja en un lote de datos para hacer predicciones. Poner h2o.predict() dentro de un bucle es un olor de código. Sería mejor llamar h2o.predict(rforest.model, test_h2o) una vez, fuera del bucle, luego descargar las predicciones en R, y cbind a test_data, y luego usarlas en esos datos combinados.

ACTUALIZACIÓN Aquí está su ejemplo cambiado para que funcione de esa manera: (He agregado la predicción como una columna adicional a los datos de prueba; hay otras formas de hacerlo, por supuesto)

test_h2o <- as.h2o(subset(test_data_finialized, select=-c(date))) p <- h2o.predict(my_gbm, test_h2o) test_data_finialized$pred = as.vector(p) mape_calc2 <- function(sub_df) { actual <- sub_df$medv mape <- 100 * mean(abs((actual - sub_df$pred)/actual)) data.frame(mape = mape) } df_list <- by(test_data_finialized, test_data_finialized$date, mape_calc2)

Debes notar que corre mucho más rápido.

ACTUALIZACIÓN ADICIONAL : by() funciona agrupando los mismos valores de su segundo argumento y procesándolos juntos. Como todas las marcas de tiempo son diferentes, está procesando una fila a la vez.

Busque en la biblioteca xts y, por ejemplo, apply.daily() para agrupar marcas de tiempo. Pero para el caso simple de querer procesar por fecha, hay un simple truco. Cambie su línea by() a:

df_list <- by(test_data_finialized, as.Date(test_data_finialized$date), mape_calc2)

El uso de as.Date() eliminará los tiempos. Por lo tanto, todas las filas en el mismo día ahora tienen el mismo aspecto y se procesan juntas.

ASIDE 2: Obtendrás mejores respuestas si haces el infame .com/help/mcve . Entonces las personas pueden ejecutar su código y pueden probar sus respuestas. También suele ser mejor usar un conjunto de datos simple que todos tenemos, por ejemplo, el iris, en lugar de sus propios datos. (Puedes hacer una regresión en cualquiera de los primeros 4 campos; el uso del iris no siempre tiene que ser una predicción de la especie).

ASIDE 3 : puede hacer MAPE completamente dentro de H2O, ya que las funciones abs() y mean() funcionarán directamente en los marcos de datos H2O (al igual que muchas otras cosas; consulte el manual de H2O): https://.com/a/43103229/841830 (No lo estoy marcando como un duplicado, ya que su pregunta era cómo adaptarse by() para usar con marcos de datos H2O, ¡no cómo calcular MAPE de manera eficiente!)


Parece que estás mezclando los tipos de datos R y H2O. Recuerde que la R de H2O es simplemente una API de R y no es lo mismo que la R. nativa. Esto significa que no puede aplicar una función R que espera un marco de datos R a un H2OFrame. Y tampoco puede aplicar una función H2O a un marco de datos R cuando espera un H2OFrame.

Como puede ver en la documentación de R, es una función que espera "un objeto R, normalmente un marco de datos, posiblemente una matriz", por lo que no puede pasar un marco H2O.

Del mismo modo, está pasando la date = H2OFrame a data.frame() .

Sin embargo, puede usar as.data.frame() para convertir un H2OFrame en un marco de datos R y luego realizar sus cálculos completamente en R.