簡體   English   中英

分組數據上的yardstick :: rmse返回錯誤和不正確的結果

[英]yardstick::rmse on grouped data returns error and incorrect results

我想評估幾個回歸模型的性能,並使用yardstick包裝計算RMSE。 這是一些示例數據

  model obs pred
1     A   1    1
2     B   1    2
3     C   1    3

當我運行以下代碼

library(yardstick)
library(dplyr)
dat %>%
 group_by(model) %>%
 summarise(RMSE = yardstick::rmse(truth = obs, estimate = pred))

我收到以下錯誤

summarise_impl(.data,點)中的錯誤:沒有適用於“ rmse”的適用方法應用於類“ c('double','numeric')”的對象。

但是,當我明確提供時. 作為第一個參數(這不應該是必要的,我認為),我沒有錯誤,但結果是不正確的。

dat %>%
 group_by(model) %>%
 summarise(RMSE = yardstick::rmse(., truth = obs, estimate = pred))
# A tibble: 3 x 2
  model   RMSE
  <fctr> <dbl>
1 A       1.29
2 B       1.29
3 C       1.29

我期待以下

# A tibble: 3 x 2
  model   RMSE
  <fctr> <dbl>
1 A       0
2 B       1.00
3 C       2.00

我知道此功能還有其他選擇,但我仍然不了解這種行為。

數據

dat <- structure(list(model = structure(1:3, .Label = c("A", "B", "C"), class = "factor"), obs = c(1, 1, 1), pred = 1:3), .Names = c("model", "obs", "pred"), row.names = c(NA, -3L), class = "data.frame")

根據幫助頁面?yardstick::rmse ,它似乎希望將數據框作為第一個參數,從而說明您遇到的錯誤。

我對新程序包的了解還不夠快,但是該函數似乎希望跨數據幀計算摘要統計信息,而不是逐行計算。 要強制它逐行運行,您需要使其認為每一行都是其自己的數據幀,並在每個數據幀中應用該函數:

library(tidyverse)
dat %>%
  group_by(model) %>%
  nest() %>% 
  mutate(rmse_res = map(data, rmse, truth = obs, estimate = pred)) %>% 
  unnest(rmse_res)

# A tibble: 3 x 3
  model  data              rmse
  <fctr> <list>           <dbl>
1 A      <tibble [1 x 2]>  0   
2 B      <tibble [1 x 2]>  1.00
3 C      <tibble [1 x 2]>  2.00

我們可以使用do函數將rmse函數應用於每個組。

dat %>%
  group_by(model) %>%
  do(data_frame(model = .$model[1], obs = .$obs[1], pred = .$pred[1], 
     RMSE = yardstick::rmse(., truth = obs, estimate = pred)))
# # A tibble: 3 x 4
# # Groups: model [3]
# model    obs  pred  RMSE
#  <fctr> <dbl> <int> <dbl>
# 1 A       1.00     1  0   
# 2 B       1.00     2  1.00
# 3 C       1.00     3  2.00

或者我們可以拆分數據幀並應用rmse函數。

dat %>%
  mutate(RMSE = dat %>%
           split(.$model) %>%
           sapply(yardstick::rmse, truth = obs, estimate = pred))
#   model obs pred RMSE
# 1     A   1    1    0
# 2     B   1    2    1
# 3     C   1    3    2

或者,我們可以將obspred列嵌套到列表列,然后應用rmse函數。

library(tidyr)

dat %>%
  nest(obs, pred) %>%
  mutate(RMSE = sapply(data, yardstick::rmse, truth = obs, estimate = pred)) %>%
  unnest()
#   model RMSE obs pred
# 1     A    0   1    1
# 2     B    1   1    2
# 3     C    2   1    3

這三種方法的輸出略有不同,但是都包含正確的RMSE計算。 在這里,我使用microbenchmark軟件包進行性能評估。

library(microbenchmark)

microbenchmark(m1 = {dat %>%
    group_by(model) %>%
    do(data_frame(model = .$model[1], obs = .$obs[1], pred = .$pred[1], 
                  RMSE = yardstick::rmse(., truth = obs, estimate = pred)))},
    m2 = {dat %>%
        mutate(RMSE = dat %>%
                 split(.$model) %>%
                 sapply(yardstick::rmse, truth = obs, estimate = pred))},
    m3 = {dat %>%
        nest(obs, pred) %>%
        mutate(RMSE = sapply(data, yardstick::rmse, truth = obs, estimate = pred)) %>%
        unnest()})

# Unit: milliseconds
# expr      min       lq     mean   median       uq       max neval
#   m1 43.18746 46.71055 50.23383 48.46554 51.05639 174.46371   100
#   m2 14.08516 14.78093 16.14605 15.74505 16.89936  24.02136   100
#   m3 28.99795 30.90407 32.71092 31.89954 33.94729  44.57953   100

結果表明, m2最快,而m1最慢。 我認為這意味着do操作通常比其他方法慢,因此,如果可能,應避免執行do操作。 盡管m2是最快的,但我個人最喜歡m3的語法。 嵌套的數據框將使我們能夠輕松匯總不同模型或不同組之間的信息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM