r - 从 'mlm' 预测 `lm()` 线性模型对象

标签 r regression linear-regression lm mlm

我有三个数据集:

响应 - 5(样本)x 10(因变量)的矩阵

预测变量 - 5(样本)x 2(独立变量)的矩阵

test_set - 10(样本)x 10(响应中定义的因变量)的矩阵

response <- matrix(sample.int(15, size = 5*10, replace = TRUE), nrow = 5, ncol = 10)
colnames(response) <- c("1_DV","2_DV","3_DV","4_DV","5_DV","6_DV","7_DV","8_DV","9_DV","10_DV") 
predictors <- matrix(sample.int(15, size = 7*2, replace = TRUE), nrow = 5, ncol = 2)
colnames(predictors) <- c("1_IV","2_IV")
test_set <- matrix(sample.int(15, size = 10*2, replace = TRUE), nrow = 10, ncol = 2)
colnames(test_set) <- c("1_IV","2_IV")

我正在使用定义为响应集和预测变量集组合的训练集来构建多元线性模型,我想使用该模型对测试集进行预测:

training_dataframe <- data.frame(predictors, response)
fit <- lm(response ~ predictors, data = training_dataframe)
predictions <- predict(fit, data.frame(test_set))

然而,预测的结果真的很奇怪:

predictions

首先,矩阵维度为 5 x 10,即响应变量中的样本数乘以 DV 数。

我对 R 中的此类分析不是很熟练,但我不应该得到一个 10 x 10 矩阵,以便我对我的 test_set 中的每一行都有预测吗?

如果您对此问题有任何帮助,我们将不胜感激, 马丁

最佳答案

您正在进入 R 中支持不佳的部分。您拥有的模型类是“mlm”,即“多重线性模型”,它不是标准的“lm”类。当您对一组共同的协变量/预测变量有几个(独立的)响应变量时,您就会得到它。虽然 lm() 函数可以适合这样的模型,但是 predict 方法对于“mlm”类来说效果很差。如果您查看 methods(predict),您会看到一个 predict.mlm*。通常对于具有“lm”类的线性模型,当您调用 predict 时会调用 predict.lm;但对于“mlm”类,调用 predict.mlm*

predict.mlm* 太原始了。它不允许 se.fit,即它不能产生预测误差、置信度/预测区间等,尽管这在理论上是可能的。它只能计算预测均值。如果是这样,我们为什么要使用 predict.mlm*?预测均值可以通过简单的矩阵-矩阵乘法获得(在标准“lm”类中,这是矩阵-向量乘法),因此我们可以自己完成。

考虑这个小的、重现的例子。

set.seed(0)
## 2 response of 10 observations each
response <- matrix(rnorm(20), 10, 2)
## 3 covariates with 10 observations each
predictors <- matrix(rnorm(30), 10, 3)
fit <- lm(response ~ predictors)

class(fit)
# [1] "mlm" "lm"

beta <- coef(fit)
#                  [,1]       [,2]
#(Intercept)  0.5773235 -0.4752326
#predictors1 -0.9942677  0.6759778
#predictors2 -1.3306272  0.8322564
#predictors3 -0.5533336  0.6218942

当您有预测数据集时:

# 2 new observations for 3 covariats
test_set <- matrix(rnorm(6), 2, 3)

我们首先需要填充一个截距列

Xp <- cbind(1, test_set)

然后做这个矩阵乘法

pred <- Xp %*% beta
#          [,1]      [,2]
#[1,] -2.905469  1.702384
#[2,]  1.871755 -1.236240

也许你已经注意到我在这里甚至没有使用数据框。 是的,这是不必要的,因为您拥有矩阵形式的所有内容。对于那些 R 向导,也许使用 lm.fit 甚至 qr.solve 更合适直截了当。


但作为一个完整的答案,必须演示如何使用 predict.mlm 来获得我们想要的结果。

## still using previous matrices
training_dataframe <- data.frame(response = I(response), predictors = I(predictors))
fit <- lm(response ~ predictors, data = training_dataframe)
newdat <- data.frame(predictors = I(test_set))
pred <- predict(fit, newdat)
#          [,1]      [,2]
#[1,] -2.905469  1.702384
#[2,]  1.871755 -1.236240

当我使用 data.frame() 时请注意 I()。当我们想要获取矩阵数据框时,这是必须的。您可以比较两者之间的区别:

str(data.frame(response = I(response), predictors = I(predictors)))
#'data.frame':  10 obs. of  2 variables:
# $ response  : AsIs [1:10, 1:2] 1.262954.... -0.32623.... 1.329799.... 1.272429.... 0.414641.... ...
# $ predictors: AsIs [1:10, 1:3] -0.22426.... 0.377395.... 0.133336.... 0.804189.... -0.05710.... ...

str(data.frame(response = response, predictors = predictors))
#'data.frame':  10 obs. of  5 variables:
# $ response.1  : num  1.263 -0.326 1.33 1.272 0.415 ...
# $ response.2  : num  0.764 -0.799 -1.148 -0.289 -0.299 ...
# $ predictors.1: num  -0.2243 0.3774 0.1333 0.8042 -0.0571 ...
# $ predictors.2: num  -0.236 -0.543 -0.433 -0.649 0.727 ...
# $ predictors.3: num  1.758 0.561 -0.453 -0.832 -1.167 ...

没有I()保护矩阵输入,数据很乱。令人惊奇的是,这不会对 lm 造成问题,但是 predict.mlm 将很难获得正确的预测矩阵,如果你不使用 I().

好吧,在这种情况下,我建议使用“列表”而不是“数据框”。 lm 中的 data 参数为predict 中的 newdata 参数允许列表输入。 “列表”是比数据框更通用的结构,它可以毫无困难地容纳任何数据结构。我们可以做到:

## still using previous matrices
training_list <- list(response = response, predictors = predictors)
fit <- lm(response ~ predictors, data = training_list)
newdat <- list(predictors = test_set)
pred <- predict(fit, newdat)
#          [,1]      [,2]
#[1,] -2.905469  1.702384
#[2,]  1.871755 -1.236240

也许最后,我应该强调使用公式接口(interface)总是安全的,而不是矩阵接口(interface)。我将使用 R 内置数据集作为一个可重现的例子。

fit <- lm(cbind(Girth, Height) ~ Volume, data = trees)

## use the first two rows as prediction dataset
predict(fit, newdata = trees[1:2, ])
#     Girth   Height
#1 9.579568 71.39192
#2 9.579568 71.39192

也许你还记得我说过 predict.mlm* 太原始,无法支持 se.fit。这是测试它的机会。

predict(fit, newdata = trees[1:2, ], se.fit = TRUE)
#Error in predict.mlm(fit, newdata = trees[1:2, ], se.fit = TRUE) : 
#  the 'se.fit' argument is not yet implemented for "mlm" objects

哎呀...置信区间/预测区间如何(实际上没有计算标准误差的能力就不可能产生这些区间)?好吧,predict.mlm* 将忽略它。

predict(fit, newdata = trees[1:2, ], interval = "confidence")
#     Girth   Height
#1 9.579568 71.39192
#2 9.579568 71.39192

所以这与 predict.lm 相比有很大的不同。

关于r - 从 'mlm' 预测 `lm()` 线性模型对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39553770/

相关文章:

machine-learning - 在监督学习中转换/缩放目标变量的好处?

python - 将系数正则化添加到 Statsmodels(或 Patsy)

algorithm - 回归目标导向行动计划

r - 在 Shiny 中使用 react 函数需要有限的 'xlim' 值

matlab - 最佳拟合散点图线

r - 对齐 R date.table 中的日期以进行线性回归

r - 两个数值向量相乘返回全 1

r - 这是将数据从 EUROSTAT 获取到 R 的解决方案吗?

r - 转换数据以在其上使用 lubridate

r - 如何在使用 Dplyr 的 Group_by 和 Summarise_at 时将 na.rm=TRUE 与 n() 一起使用