gpt4 book ai didi

r - lm() 和 predict.lm() 的奇怪行为取决于显式命名空间访问器的使用

转载 作者:行者123 更新时间:2023-12-04 07:33:10 29 4
gpt4 key购买 nike

我对 lm 的一些令人不安的行为感兴趣函数和相关的predict.lm R 中的函数。splines基础包提供函数bs生成 b 样条展开,然后可用于使用 lm 拟合样条模型,一个通用的线性模型拟合函数。
lmpredict.lm函数具有许多利用公式和术语的内置便利性。如果调用bs()嵌套在 lm 中调用,则用户可以向 predict 提供单变量数据,并且此数据将自动扩展为适当的 b 样条基础。然后像往常一样预测这个扩展的数据矩阵。

library(splines)

x <- sort(runif(50, 0, 10))
y <- x^2

splineModel <- lm(y ~ bs(x, y, degree = 3, knots = c(3, 6)))

newData <- data.frame(x = 4)
prediction <- predict(splineModel, newData) # 16

plot(x, y)
lines(x, splineModel$fitted.values, col = 'blue3')
points(newData$x, prediction, pch = 3, cex = 3, col = 'red3')
legend("topleft", legend = c("Data", "Fitted Values", "Predicted Value"),
pch = c(1, NA, 3), col = c('black', 'blue3', 'red3'), lty = c(NA, 1, NA))

正如我们所看到的,这非常有效:

enter image description here

当一个人使用 :: 时,就会发生奇怪的事情。运算符明确指出 bs函数从 splines 的命名空间导出包裹。除了该更改之外,以下代码段是相同的:
library(splines)

x <- sort(runif(50, 0, 10))
y <- x^2

splineModel <- lm(y ~ splines::bs(x, y, degree = 3, knots = c(3, 6)))

newData <- data.frame(x = 4)
prediction <- predict(splineModel, newData) # 6.40171

plot(x, y)
lines(x, splineModel$fitted.values, col = 'blue3')
points(newData$x, prediction, pch = 3, cex = 3, col = 'red3')
legend("topleft", legend = c("Data", "Fitted Values", "Predicted Value"),
pch = c(1, NA, 3), col = c('black', 'blue3', 'red3'), lty = c(NA, 1, NA))

enter image description here

如果 splines 则在第二个片段中产生完全相同的结果。从未使用 library 附加软件包首先。我想不出使用 :: 的另一种情况。已加载包上的运算符(operator)会更改程序行为。

使用 splines 中的其他函数也会出现相同的行为。像自然样条基础实现 ns .有趣的是,在这两种情况下,“y 帽子”或拟合值都是合理的并且相互匹配。据我所知,除了属性名称外,拟合的模型对象是相同的。

我一直无法确定这种行为的来源。虽然这可能读起来像错误报告,但我的问题是
  • 为什么会这样?我一直在努力跟进 predict.lm但无法确定分歧发生的位置。
  • 这是某种预期的行为,如果是这样,我在哪里可以了解更多信息?
  • 最佳答案

    所以问题是模型需要跟踪使用原始数据计算的节点,并在预测新数据时使用这些值。这通常发生在 model.frame()调用lm()称呼。 bs()函数返回一个类 "bs"并且在制作 model.frame 时,该列被发送到 splines:::makepredictcall.bs试图捕捉边界结。 (您可以在 makepredictcall 函数中看到 model.frame.default 调用。)

    但是如果我们比较结果

    splineModel1 <- lm(y ~ bs(x, y, degree = 3, knots = c(3, 6)))
    attr(terms(splineModel1), "predvar")
    # list(y, bs(x, degree = 3L, knots = c(3, 6), Boundary.knots = c(0.275912734214216,
    # 9.14309860439971), intercept = FALSE))

    splineModel2 <- lm(y ~ splines::bs(x, y, degree = 3, knots = c(3, 6)))
    attr(terms(splineModel2), "predvar")
    # list(y, splines::bs(x, y, degree = 3, knots = c(3, 6)))

    注意第二个没有捕获 Boundary.knots .这是因为 splines:::makepredictcall.bs实际查看调用名称的函数
    function (var, call) {
    if (as.character(call)[1L] != "bs")
    return(call)
    ...
    }

    当您使用 splines::bs在公式中,然后 as.character(call)[1L]返回 "splines::bs"不匹配 "bs"所以什么也没有发生。我不清楚为什么要进行此检查。似乎方法调度应该足以假设它是 bs目的。

    在我看来,这似乎不是理想的行为,可能应该修复。但是函数 bs()不应该在没有加载包的情况下调用,因为像 makepredictcall.bs 这样的函数也不要导入,因此这些对象的自定义调度将被破坏。

    关于r - lm() 和 predict.lm() 的奇怪行为取决于显式命名空间访问器的使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43505053/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com