当 lm 的预测值没有方差时,为什么会有 R^2 值(以及决定它的因素)?

机器算法验证 r 回归
2022-03-02 12:19:51

考虑以下 R 代码:

example <- function(n) {
    X <- 1:n
    Y <- rep(1,n)
    return(lm(Y~X))
}
#(2.13.0, i386-pc-mingw32)
summary(example(7))    #R^2 = .1963
summary(example(62))   #R^2 = .4529
summary(example(4540)) #R^2 = .7832
summary(example(104))) #R^2 = 0
#I did a search for n 6:10000, the result for R^2 is NaN for
#n = 2, 4, 16, 64, 256, 1024, 2085 (not a typo), 4096, 6175 (not a typo), and 8340 (not a typo)

查看http://svn.r-project.org/R/trunk/src/appl/dqrls.f)并没有帮助我理解发生了什么,因为我不知道 Fortran。在另一个问题中,有人回答说,浮点机器容差误差应归咎于 X 的系数接近但不完全为 0。

R2coef(example(n))["X"]当 for 的值接近 0更大。但是......

  1. 为什么有一个值呢? R2
  2. 是什么(具体)决定了它?
  3. 为什么结果看似有序的进展NaN
  4. 为什么违反该进展?
  5. 这是什么“预期”行为?
3个回答

我很好奇你问这个问题的动机。我想不出这种行为很重要的实际原因;求知欲是另一种(和 IMO 更明智的)原因。我认为您无需了解 FORTRAN 即可回答此问题,但我认为您确实需要了解 QR 分解及其在线性回归中的用途。如果您将dqrls其视为计算 QR 分解并返回有关它的各种信息的黑匣子,那么您可能能够追踪这些步骤......或者直接进入summary.lm并追踪以查看 R^2 是如何计算的。尤其:

mss <- if (attr(z$terms, "intercept")) 
          sum((f - mean(f))^2)
       else sum(f^2)
rss <- sum(r^2)
## ... stuff ...
ans$r.squared <- mss/(mss + rss)

然后您必须返回lm.fit并查看拟合值的计算方式r1 <- y - z$residuals(即响应减去残差)。现在你可以弄清楚是什么决定了残差的值,以及减去它的平均值的值是否正好为零,然后从那里计算出计算结果......

正如 Ben Bolker 所说,这个问题的答案可以在summary.lm().

这是标题:

function (object, correlation = FALSE, symbolic.cor = FALSE, 
    ...) 
{

所以,让我们x <- 1:1000; y <- rep(1,1000); z <- lm(y ~ x)来看看这个稍作修改的摘录:

    p <- z$rank
    rdf <- z$df.residual
    Qr <- stats:::qr.lm(z)
    n <- NROW(Qr$qr)
    r <- z$residuals
    f <- z$fitted.values
    w <- z$weights
    if (is.null(w)) {
        mss <- sum((f - mean(f))^2)
        rss <- sum(r^2)
    }
    ans <- z[c("call", "terms")]
    if (p != attr(z$terms, "intercept")) {
        df.int <- 1L
        ans$r.squared <- mss/(mss + rss)
        ans$adj.r.squared <- 1 - (1 - ans$r.squared) * ((n - 
            df.int)/rdf)
    }

注意 ans $ r.squared 是 ...0.4998923

用一个问题来回答一个问题:我们从中得到什么?:)

我相信答案在于 R 如何处理浮点数。我认为mssrss是非常小的(平方)舍入误差的总和,因此约为 0.5。至于进展,我怀疑这与 +/- 近似值抵消为 0 所需的值的数量有关(对于,这可能是这些值的来源)。不过,我不知道为什么这些值与进度不同。R2mssrss0/0NaN2^(1:k)


更新 1:这是来自 R-help 的一个很好的线程,解决了 R中未解决下溢警告的一些原因。

此外,这个 SO Q&A有许多关于下溢、更高精度算术等的有趣帖子和有用的链接。

R2定义为 ( http://en.wikipedia.org/wiki/R_squared ),所以如果平方和总和为 0,那么它是未定义的。我认为 R 应该显示错误消息。R2=1SSerrSStot