简单线性回归模型的迭代

Iteration for simple linear regression model

我想 fit/train 一个预测模型并以交互方式进行,也就是说,例如,我在选定的时间段内每 50 天训练一次我的模型(此处:2020 年全年) .基本上我想预测第二列 (DE) 并使用剩余的列和参数进行预测。我的数据 table 可能如下所示:

set.seed(123)
days <- 50
## Create random data table: ##
dt.data <- data.table(date = seq(as.Date('2020-01-01'), by = '1 day', length.out = 366),
                      "DE" = rnorm(366, 35, 1), "Wind" = rnorm(366, 5000, 2), "Solar" = rnorm(366, 3, 2),
                      "Nuclear" = rnorm(366, 100, 5), "ResLoad" = rnorm(366, 200, 3),  check.names = FALSE)

我的数据的日期范围 table、预测变量的数量和天数 (days) 总是不同的。我已经为整个数据 table 完成了模型 fitting/training 一次,但我不知道如何每 50 天迭代一次?在这里您可以看到我的模型适合线性模型的代码片段:

v.trainDate <- dt.data$date
## Delete column "date" of train data for model fitting: ##
dt.data <- dt.data[, c("date") := NULL]

## MODEL FITTING: ##
## Linear Model: ##
lmModel <- stats::lm(DE ~ .-1, data = dt.data)

## Train PREDICTION with lmModel: ##
dt.data$prediction <- stats::predict.glm(lmModel, dt.data)
## Add date columns to dt.train: ##
dt.data <- data.table(date = v.trainDate, dt.data)

我最后想要的是我首先用我的数据训练模型从 2020-01-012020-02-20(前 50 天)并预测 DE 价格这个拟合模型 lmModel 用于我数据的前五十个条目 table。接下来 运行 应该是将我的模型从 2020-02-20 训练到 2020-04-10(接下来的 50 天)并预测这新 50 天的值。这应该完成到 2020 年 12 月的最后一天。最后我需要一个列,称为 prediction 正如你在我的代码片段中看到的那样,但是这个列应该包含 [=13= 的交互构建的预测]价格。

我还想在每次迭代后将变量重要性保存在某处?这样我就可以看到哪个变量在前 50 天内对 DE 价格的影响最大,等等。有人知道这是怎么回事吗?

这是一种方法,使用嵌套数据框和 map() 函数的优点。基本上首先创建一个开始日期的数据集,然后选择与该开始日期相关的数据,然后 运行 回归并提取结果。最终输出显示为数据集,其中行代表样本的第一个日期,列代表预测数据的日期。

library(tidyverse)
days <- 50
set.seed(123)
## Create random data table: ##
data <- tibble(date = seq(as.Date('2020-01-01'), by = '1 day', length.out = 366),
                  "DE" = rnorm(366, 35, 1), "Wind" = rnorm(366, 5000, 2), "Solar" = rnorm(366, 3, 2),
                  "Nuclear" = rnorm(366, 100, 5), "ResLoad" = rnorm(366, 200, 3),  check.names = FALSE)


data_out <- tibble(train_start_date= tail(data$date, -50)) %>% 
  mutate(data = map(train_start_date, ~filter(data, date >=.x) %>% 
                      head(50)),
         lmModel =map(data, ~stats::lm(DE ~ .-1, data = .x)),
         prediction= map2(lmModel, data,  ~tibble(train_end_date=max(.y$date), 
                                                  prediction=predict(.x), 
                                                 prediction_date = .y$date))) %>% 
  select(train_start_date, prediction) %>% 
  unnest(prediction) %>% 
  mutate(train_n_days = as.integer(train_end_date-train_start_date)+1) %>% 
  select(train_start_date, train_end_date, train_n_days, prediction_date, prediction)

data_out
#> # A tibble: 14,575 x 5
#>    train_start_date train_end_date train_n_days prediction_date prediction
#>    <date>           <date>                <dbl> <date>               <dbl>
#>  1 2020-02-20       2020-04-09               50 2020-02-20            35.0
#>  2 2020-02-20       2020-04-09               50 2020-02-21            35.0
#>  3 2020-02-20       2020-04-09               50 2020-02-22            35.1
#>  4 2020-02-20       2020-04-09               50 2020-02-23            35.2
#>  5 2020-02-20       2020-04-09               50 2020-02-24            34.6
#>  6 2020-02-20       2020-04-09               50 2020-02-25            35.2
#>  7 2020-02-20       2020-04-09               50 2020-02-26            35.0
#>  8 2020-02-20       2020-04-09               50 2020-02-27            35.0
#>  9 2020-02-20       2020-04-09               50 2020-02-28            35.1
#> 10 2020-02-20       2020-04-09               50 2020-02-29            35.1
#> # … with 14,565 more rows

reprex package (v1.0.0)

于 2021-02-15 创建

下面的 calclm 函数计算预测,calcImportance 函数计算变量重要性。

by=seq_len(nrow(dt.data)) %/% days 参数使用 data.table 将数据集拆分为 days 个块并将之前的函数应用于每个块:

library(data.table)
library(caret)

## Create random data table: ##
dt.data <- data.table(date = seq(as.Date('2020-01-01'), by = '1 day', length.out = 366),
                      "DE" = rnorm(366, 35, 1), "Wind" = rnorm(366, 5000, 2), "Solar" = rnorm(366, 3, 2),
                      "Nuclear" = rnorm(366, 100, 5), "ResLoad" = rnorm(366, 200, 3),  check.names = FALSE)

set.seed(123)
days <- 50

# Prediction calculation
calcPred <- function(data) {
  lmModel <- stats::lm(DE ~ .-1-date, data = data)
  stats::predict.glm(lmModel, data)
}

# Importance calculation
calcImportance <- function(data) {
  lmModel <- stats::lm(DE ~ .-1-date, data = data)
  terms <- attr(lmModel$terms , "term.labels")
  varimp <- caret::varImp(lmModel)
  importance <- data[,.(date,imp = t(varimp))]
}

importance.data <- data.table::copy(dt.data)
importance.data[,calcImportance(.SD),by=seq_len(nrow(dt.data)) %/% days]
#>      seq_len       date imp.Wind imp.Solar imp.Nuclear imp.ResLoad
#>   1:       0 2020-01-01 4.598201 2.4726894   0.7993097   1.7153244
#>   2:       0 2020-01-02 4.598201 2.4726894   0.7993097   1.7153244
#>   3:       0 2020-01-03 4.598201 2.4726894   0.7993097   1.7153244
#>   4:       0 2020-01-04 4.598201 2.4726894   0.7993097   1.7153244
#>   5:       0 2020-01-05 4.598201 2.4726894   0.7993097   1.7153244
#>  ---                                                              
#> 362:       7 2020-12-27 1.093177 0.2558265   0.1610440   0.5383146
#> 363:       7 2020-12-28 1.093177 0.2558265   0.1610440   0.5383146
#> 364:       7 2020-12-29 1.093177 0.2558265   0.1610440   0.5383146
#> 365:       7 2020-12-30 1.093177 0.2558265   0.1610440   0.5383146
#> 366:       7 2020-12-31 1.093177 0.2558265   0.1610440   0.5383146

dt.data[,c('prediction'):=calcPred(.SD),by=seq_len(nrow(dt.data)) %/% days]

dt.data
#>            date       DE     Wind      Solar   Nuclear  ResLoad prediction
#>   1: 2020-01-01 36.51972 5000.608  1.4283653  92.19844 200.1163   35.02625
#>   2: 2020-01-02 34.96544 4999.235  0.3860045  92.29005 203.2613   34.96200
#>   3: 2020-01-03 35.16448 5002.232 -1.4450524 100.32920 202.5225   35.67255
#>   4: 2020-01-04 36.07978 5000.564 -0.9137483  98.07459 206.3788   35.13325
#>   5: 2020-01-05 35.10967 4997.606  4.9788029 101.27625 201.8148   34.29788
#>  ---                                                                      
#> 362: 2020-12-27 34.98190 4997.936  2.6117305  98.33027 195.1352   34.80871
#> 363: 2020-12-28 35.16974 4998.799  1.0776123 108.26064 195.2474   35.01232
#> 364: 2020-12-29 35.37956 4998.651  3.9252237 102.87948 201.0266   35.09362
#> 365: 2020-12-30 35.51517 4999.428  5.9747031  92.38721 196.4204   34.60962
#> 366: 2020-12-31 33.53278 5001.911  3.5062344  93.60744 197.5292   34.85689