为什么 h2o.r2() 与手动计算的 R^2 不匹配?

问题描述 投票:0回答:2

我正在使用 h2o.r2(),但它给了我一个与我手动计算的值非常不同的值...它似乎并不总是有这种行为...例如对于简单的线性模型,它似乎有效。

无论如何,我不确定我是否使用了错误的方式或者这是否是一个错误?

library(tidyverse)
# fit AML, get leader...
fit_aml_H2O = function(X_df, Y_vec) {
  library(h2o); h2o.init()
  
  df = cbind(X_df, Y_vec)
  colnames(df)[[ncol(df)]]='Y'
  df = as.h2o(df)
  aml <- h2o.automl(x=colnames(X_df), y='Y', training_frame=df, nfolds=0,
                    max_models = 15, max_runtime_secs=90)
  leader = h2o.get_best_model(aml)
  cat('R^2: ', h2o.r2(leader, train=T))
  return(leader)
}

# manually compute R^2 (verified to work)
R2 = function(Y_pred, Y_true) {
  MSE = mean((as.numeric(Y_true)-as.numeric(Y_pred))**2)
  R2 = 1-MSE/var(Y_true)
  return(R2)
}

data(iris)

X_df = iris %>% select(-Petal.Length)
Y = iris %>% select(Petal.Length)
model = fit_aml_H2O(X_df, Y)

X_df = as.h2o(X_df)
Y_pred = h2o.predict(model, newdata=X_df)$predict
(R2_train = R2(Y_pred[,1], Y[,1]))
cat('R^2 (manually computed): ', R2_train, '\n')
cat('R^2 (reported by H2O): ', h2o.r2(model,train=T), '\n')
cat('difference between manual R^2 & H2O reported R^2: ',
    abs(R2_train-h2o.r2(model,train=T)), '\n')
stopifnot(all.equal(h2o.r2(model,train=T), R2_train))
r h2o
2个回答
1
投票

docs 没有描述该算法,但可能有用的是,

h2o.r2()
不会计算它:它从创建模型时计算的指标中获取值: https://github.com/h2oai/h2o-3/blob/6758ed00b5200c782cd2bbebf0094374757dc472/h2o-r/h2o-package/R/models.R#L2018

无论如何,差异是数据集吗?

h2o.r2(model,train=T)
将仅评估训练数据,而您正在传递整个
X_df

对于简单的线性模型,它似乎有效。

嗯,您可以证明 R2 仅对简单的线性模型有意义。事实上,人们会提出理由,那样就没有任何意义了。


1
投票

手动 R² 计算中存在一个错误 - R 数值向量的第一个值通过 H2O 列的操作进行广播。

为了看看发生了什么,我尝试了以下操作:

> Y_true <- Y[,1]
> Y_pred <- Y_pred[,1]
> (as.numeric(Y_true)-as.numeric(Y_pred))
       predict
1 -0.085572158
2 -0.090655887
3  0.090492763
4  0.127857837
5  0.005002167
6 -0.335313060

[150 rows x 1 column] 
> (as.numeric(Y_true)-as.numeric(Y_pred))+as.numeric(Y_pred) 
  predict
1     1.4
2     1.4
3     1.4
4     1.4
5     1.4
6     1.4

[150 rows x 1 column] 
> Y_true
  [1] 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 1.5 1.6 1.4 1.1 1.2 1.5 1.3 1.4 1.7 1.5 1.7 1.5 1.0 1.7 1.9 1.6 1.6 1.5 1.4 1.6 1.6 1.5 1.5 1.4 1.5 1.2 1.3 1.4
 [39] 1.3 1.5 1.3 1.3 1.3 1.6 1.9 1.4 1.6 1.4 1.5 1.4 4.7 4.5 4.9 4.0 4.6 4.5 4.7 3.3 4.6 3.9 3.5 4.2 4.0 4.7 3.6 4.4 4.5 4.1 4.5 3.9 4.8 4.0 4.9 4.7 4.3 4.4
 [77] 4.8 5.0 4.5 3.5 3.8 3.7 3.9 5.1 4.5 4.5 4.7 4.4 4.1 4.0 4.4 4.6 4.0 3.3 4.2 4.2 4.2 4.3 3.0 4.1 6.0 5.1 5.9 5.6 5.8 6.6 4.5 6.3 5.8 6.1 5.1 5.3 5.5 5.0
[115] 5.1 5.3 5.5 6.7 6.9 5.0 5.7 4.9 6.7 4.9 5.7 6.0 4.8 4.9 5.6 5.8 6.1 6.4 5.6 5.1 5.6 6.1 5.6 5.5 4.8 5.4 5.6 5.1 5.1 5.9 5.7 5.2 5.0 5.2 5.4 5.1

您可以通过更改将其转换为 R

MSE = mean((as.numeric(Y_true)-as.numeric(Y_pred))**2)

MSE = mean((as.numeric(as.vector(Y_true))-as.numeric(as.vector(Y_pred)))**2)

或者通过改变

将其转化为H2O
MSE = mean((as.numeric(Y_true)-as.numeric(Y_pred))**2)

MSE = mean((as.numeric(as.h2o(Y_true))-as.numeric(as.h2o(Y_pred)))**2)

注意: 即使如此,您可能会注意到手动计算的 R² 和 H2O 的 R² 有所不同。我相信这是由 AutoML 中在

nfolds=0
时使用的训练/测试分割引起的(例如,提前停止)。 (
difference between manual R^2 & H2O reported R^2:  0.0005075975
).

注 2:

as.numeric
可能是不必要的,但我将其保留在那里,以防万一您需要它来存储数据。

© www.soinside.com 2019 - 2024. All rights reserved.