在H2o中计算MAPE:错误:提供的列类型POSCct未知。

8

以下是我回答的问题:R或Python - 循环测试数据 - 预测验证接下来的24小时(每天96个值)

我想使用H2o软件包预测明天的情况。 您可以在上述链接中找到有关我的数据集的详细说明

H2o中的数据维度不同。

因此,在进行预测后,我想计算MAPE。

我必须将训练和测试数据更改为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)

上述代码可以很好地进行“非H2O”预测验证,并计算每天的MAPE。
我试图将H2O预测模型转换为普通格式,但根据以下链接所述,这是不可能的:https://dev59.com/xJrga4cB1Zd3GeqPkkzr#39221269
要在H2O中进行预测:
例如,假设我们想创建一个随机森林模型。
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)

然后,我们可以得到完整数据集的预测结果,如下所示。
predict.rforest <- as.data.frame(h2o.predict(rforest.model, test_h2o)

但是在我的情况下,我正在尝试使用mape_calc获得一天的预测。


注意:欢迎使用R或Python进行思考。

更新2(可重现的示例):**按照@Darren Cook的步骤:

我提供了一个更简单的示例 - 波士顿房屋数据集。

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)

我现在遇到的错误如下:

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

ERROR MESSAGE:

提供的列类型POSIXct未知。由于参数无效,无法继续解析。


请提供一个可重现的示例:https://stackoverflow.com/help/mcve 你没有使用公共数据集,所以没有人可以直接运行这段代码。 - Erin LeDell
3个回答

10

H2O运行在单独的进程中,与R分开(无论H2O是在本地服务器还是远程数据中心)。 H2O数据和模型保存在那个H2O进程中,R看不到它们。

dH <- as.h2o(dR)所做的是将R数据框复制到H2O的内存空间中。 dH然后是描述H2O数据帧的R变量。也就是说,它是一个指针或句柄; 它不是数据本身。

dR <- as.data.frame(dH)所做的是将数据从H2O进程的内存复制到R进程的内存中。 (当dH描述单个列时,as.vector(dH)执行相同操作)

因此,最简单的修改您的mape_calc()方法的方法(假设sub_df是R数据框)是更改前两行如下:

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)
}

即上传sub_df到H2O,然后将其提供给h2o.predict()。然后使用as.vector()下载所做出的预测。

这是相对于您原始代码的版本。因此请保留此原始版本:

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

即,不要直接在test_h2o上使用by()函数。


根据编辑后的问题更新:

我对你的示例代码进行了两个更改。首先,我从sub_df中删除了日期列。那是导致错误消息的原因。

第二个更改只是为了简化返回类型;这并不重要,但是之前你最终得到了重复的日期列。

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()对一批数据进行预测时,它的效率最高。将h2o.predict()放在循环内部是一个代码味道的问题。你最好在循环外部调用h2o.predict(rforest.model, test_h2o)一次,然后下载预测结果到R中,并将其与测试数据进行cbind,然后在该组合数据上使用by

UPDATE 这里是按照上述方式修改后的示例:(我已将预测结果作为额外列添加到测试数据中;当然还有其他方法可以实现)

 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)

请注意它运行速度更快。

补充更新by()函数通过对第二个参数相同的值进行分组,并将它们一起处理。由于所有时间戳都不同,您正在逐行处理。

查看xts库和例如apply.daily()来分组时间戳。但是如果只想按日期处理简单情况,则有一个简单的技巧。 将by()行更改为:

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

使用as.Date()会去掉时间。因此,同一天内的所有行现在看起来都相同,并且会一起处理。

ASIDE 2:如果您创建“最小示例”(请参见此处),您将获得更好的回复。然后,人们可以运行您的代码并测试其答案。通常最好使用每个人都有的简单数据集,例如鸢尾花数据集(iris),而不是您自己的数据。(您可以对前4个字段中的任何一个执行回归;使用鸢尾花数据集不一定总是要预测物种。)

ASIDE 3:您可以完全在H2O中执行MAPE,因为abs()mean()函数可以直接在H2O数据框上工作(还有很多其他事情-请参见H2O手册):https://stackoverflow.com/a/43103229/841830 (我不会将其标记为重复内容,因为您的问题是如何将by()适用于H2O数据框,而不是如何有效地计算MAPE!)


如果您能通过一个可重现的示例展示结果,那将非常棒。再次感谢您的努力。 - King Julien
@KingJulien 如果您能够修改您的问题,让它具有完全可重现的示例,我就可以对其进行编辑/测试。 (请记住,可重现的示例很可能以“library(h2o)”开头,定义所有数据等。也就是说,允许我将其复制并粘贴到R会话中运行,并看到您收到的相同错误消息,而无需执行任何其他操作。) - Darren Cook
1
亲爱的@Dareen Cook,这是我的新问题。我希望它很清楚:https://stackoverflow.com/questions/52138212/how-to-predict-day-ahead-using-h20 请随意编辑任何内容。我只想每次取96个值-每15分钟采样一次-并对其进行预测。 - King Julien
@KingJulien,请查看我关于by如何工作的额外更新。 - Darren Cook
@KingJulien 这是一个问答网站,而不是为你编写代码的网站;-) 如果有需要的话,我建议你提出一个新的具体问题,或者考虑雇用开发人员或顾问来帮助你。 - Darren Cook
显示剩余10条评论

5
看起来你混淆了R和H2O的数据类型。请记住,H2O的R仅仅是一个R API,并不同于本地R。这意味着你不能将期望一个R数据框的R函数应用于H2OFrame上。同样地,当期望一个H2OFrame时,你也不能将一个H2O函数应用于R数据框上。
正如你从R文档中看到的那样,by是一个期望“一个R对象(通常是数据框,可能是矩阵)”的函数,因此你不能传入一个H2O frame。
类似地,你正在将date = H2OFrame传递给data.frame()
但是你可以使用as.data.frame()将H2OFrame转换为R数据框,然后在R中进行全部计算。

1
如果你的预测框架不是很大,我建议将H2O预测框架转换为R框架,并继续使用之前使用过的R函数。 - Lauren

0

问题可能就是文件格式吗?我从 Excel 导入后运行代码时出现了 "Provided column type POSIXct is unknown" 错误。

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

我将源文件更改为制表符分隔(没有其他更改),问题就解决了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接