R函数`poly`到底是做什么的?

70

我已经阅读了手册页面 ?poly(我承认我并没有完全理解),并且也在书籍《统计学习导论》中阅读了这个函数的描述。

我的目前理解是,调用 poly(horsepower, 2) 应该等价于写成 horsepower + I(horsepower^2)。然而,以下代码的输出似乎与此相矛盾:

library(ISLR)

summary(lm(mpg~poly(horsepower,2), data=Auto))$coef

    #                       Estimate Std. Error   t value      Pr(>|t|)
    #(Intercept)            23.44592  0.2209163 106.13030 2.752212e-289
    #poly(horsepower, 2)1 -120.13774  4.3739206 -27.46683  4.169400e-93
    #poly(horsepower, 2)2   44.08953  4.3739206  10.08009  2.196340e-21

summary(lm(mpg~horsepower+I(horsepower^2), data=Auto))$coef

    #                    Estimate   Std. Error   t value      Pr(>|t|)
    #(Intercept)     56.900099702 1.8004268063  31.60367 1.740911e-109
    #horsepower      -0.466189630 0.0311246171 -14.97816  2.289429e-40
    #I(horsepower^2)  0.001230536 0.0001220759  10.08009  2.196340e-21

我的问题是,为什么输出结果不一致,poly 究竟是做了什么?


3
请看这个问题的答案:http://mathoverflow.net/questions/38864/visualizing-orthogonal-polynomials - Kieran
我刚才看了一下(还不是很理解),但我仍然想知道,在这个上下文中,poly(horsepower,2)生成的闭式公式到底是什么? - merlin2011
尝试使用 poly(horsepower, degree=2, raw=TRUE); 您正在将 2 作为错误的参数传递,并且 raw 默认为 FALSE。 - baptiste
1
@baptiste,你的建议可以让 poly 生成与显式公式相同的输出,但我仍然想知道 poly 在没有该参数的情况下生成的“正交多项式”的实际形式。此外,根据手册,我传递了2作为度数: “尽管正式上来说,“degree”应该被命名(因为它遵循“...”), 但长度为1的未命名第二个参数将被解释为度数。” - merlin2011
1
关于 ... 的观点很好,但最好的做法是以它命名参数。 - baptiste
3个回答

82

原始多项式

若要得到问题中的普通多项式,请使用raw = TRUE。然而,在回归中使用普通多项式存在一个不良方面。例如,如果我们拟合一个二次多项式,然后再拟合一个三次多项式,那么三次多项式的低阶系数都将与二次多项式不同,即在进行三次拟合之前为56.900099702、-0.466189630、0.001230536的二次系数变为了6.068478e+01、-5.688501e-01、2.079011e-03。

library(ISLR)
fm2raw <- lm(mpg ~ poly(horsepower, 2, raw = TRUE), Auto)
cbind(coef(fm2raw))
##                                          [,1]
## (Intercept)                      56.900099702
## poly(horsepower, 2, raw = TRUE)1 -0.466189630
## poly(horsepower, 2, raw = TRUE)2  0.001230536

fm3raw <- lm(mpg ~ poly(horsepower, 3, raw = TRUE), Auto)
cbind(coef(fm3raw))
##                                           [,1]
## (Intercept)                       6.068478e+01
## poly(horsepower, 3, raw = TRUE)1 -5.688501e-01
## poly(horsepower, 3, raw = TRUE)2  2.079011e-03
## poly(horsepower, 3, raw = TRUE)3 -2.146626e-06

正交多项式

我们真正想要的是,以一种方式添加三次项,使得在用三次拟合重新拟合后,使用二次项进行拟合的较低阶系数保持不变。为此,需要对poly(horsepower, 2, raw = TRUE)的列进行线性组合,并对poly(horsepower, 3, raw = TRUE)进行相同处理,以使二次拟合中的列彼此正交,三次拟合亦然。这足以确保在添加高阶系数时较低阶系数不会改变。请注意,在下面两组数据中,前三个系数现在相同(而上面不同)。也就是说,在下面两种情况下,前三个较低阶系数均为23.44592、-120.13774和44.08953。

fm2 <- lm(mpg ~ poly(horsepower, 2), Auto)
cbind(coef(fm2))
##                            [,1]
## (Intercept)            23.44592
## poly(horsepower, 2)1 -120.13774
## poly(horsepower, 2)2   44.08953

fm3 <- lm(mpg ~ poly(horsepower, 3), Auto)
cbind(coef(fm3))
##                             [,1]
## (Intercept)            23.445918
## poly(horsepower, 3)1 -120.137744
## poly(horsepower, 3)2   44.089528
## poly(horsepower, 3)3   -3.948849

相同的预测

重要的是,由于poly(horsepower, 2)的列只是poly(horsepower, 2, raw = TRUE)的列的线性组合,因此这两个二次模型(正交和原始)表示相同的模型(即它们给出相同的预测结果),只有参数化不同。例如,拟合值是相同的:

all.equal(fitted(fm2), fitted(fm2raw))
## [1] TRUE

对于原始的和正交的立方模型也同样适用。

正交性

我们可以验证多项式确实具有正交的列,这些列还与截距正交:

nr <- nrow(Auto)
e <- rep(1, nr) / sqrt(nr) # constant vector of unit length
p <- cbind(e, poly(Auto$horsepower, 2))
zapsmall(crossprod(p))
##   e 1 2
## e 1 0 0
## 1 0 1 0
## 2 0 0 1

残差平方和

正交多项式的另一优点是,由于poly生成的矩阵的列长度相等且彼此正交(也与截距列正交),因此添加立方项所导致的残差平方和的减少量就是响应向量在模型矩阵的立方列上投影长度的平方。

# these three give the same result

# 1. squared length of projection of y, i.e. Auto$mpg, on cubic term column
crossprod(model.matrix(fm3)[, 4], Auto$mpg)^2
##         [,1]
## [1,] 15.5934

# 2. difference in sums of squares
deviance(fm2) - deviance(fm3) 
## [1] 15.5934

# 3. difference in sums of squares from anova
anova(fm2, fm3) 
## 
## Analysis of Variance Table
## 
## Model 1: mpg ~ poly(horsepower, 2)
## Model 2: mpg ~ poly(horsepower, 3)
##   Res.Df    RSS Df Sum of Sq      F Pr(>F)
## 1    389 7442.0                           
## 2    388 7426.4  1    15.593 0.8147 0.3673  <-- note Sum of Sq value

请问为什么要将 e 除以 nr 的平方根来计算它呢? - HelloWorld
1
因此,它的长度 sqrt(crossprod(e, e)) 为1。 - G. Grothendieck
你说“poly(horsepower, 2)的列只是poly(horsepower, 2, raw = TRUE)的列的线性组合”。是否可能精确地提取线性组合是什么?这样我就可以手动从非正交多项式中推导出正交多项式,或者编写一个方程。 - Gimelist
4
给定 h <- Auto$horsepower; p <- poly(h, 2); p.raw <- poly(h, 2, raw = TRUE); co <- coef(lm(p ~ p.raw)),我们有 co 是所需的变换矩阵,即 cbind(1, p.raw) %*% co 等于 p。此外,这个变换矩阵是 cbind(1, p.raw) 的格兰-施密特分解的 R 矩阵的逆矩阵。也就是说,library(pracma); gs <- gramSchmidt(cbind(1, p.raw)); cbind(1, p.raw) %*% solve(gs$R)[, -1] 等于 p - G. Grothendieck
1
你能否添加这个问题的答案:这些多项式关于哪个内积是正交的?这是我无法理解的。我习惯于将Hermite、Laguerre、Legendre等多项式视为使用相对于特定内积的Gram-Schmidt构造的多项式。谢谢! - Adrian Keister
1
这是普通的内积。请参见答案中的正交性部分。 - G. Grothendieck

40

在统计模型中引入多项式项时,通常的动机是确定响应是否“弯曲”,以及当添加该项时曲率是否“显著”。加入 +I(x^2) 项的结果是,由于拟合过程中的位置不同,可能会放大微小的偏差,并将其视为由于曲率项而误解为数据范围的一端或另一端的波动。这导致了错误地宣布“显著性”的声明。

如果只是加入一个带有 I(x^2) 的平方项,那么在 x > 0 的域内至少也会与x高度相关。使用 poly(x,2) 则创建了一组“弯曲”的变量,其中线性项与x的相关性不高,而曲率在整个数据范围内大致相同。(如果想了解统计理论,请搜索“正交多项式”。)只需键入 poly(1:10, 2) 并查看两列即可。

poly(1:10, 2)
                1           2
 [1,] -0.49543369  0.52223297
 [2,] -0.38533732  0.17407766
 [3,] -0.27524094 -0.08703883
 [4,] -0.16514456 -0.26111648
 [5,] -0.05504819 -0.34815531
 [6,]  0.05504819 -0.34815531
 [7,]  0.16514456 -0.26111648
 [8,]  0.27524094 -0.08703883
 [9,]  0.38533732  0.17407766
[10,]  0.49543369  0.52223297
attr(,"degree")
[1] 1 2
attr(,"coefs")
attr(,"coefs")$alpha
[1] 5.5 5.5

attr(,"coefs")$norm2
[1]   1.0  10.0  82.5 528.0

attr(,"class")
[1] "poly"   "matrix"

“二次”项以5.5为中心,线性项已向下移动,使其在相同的x点为0(模型中的隐含(Intercept)项在请求预测时用于将所有内容移回原位)。


11
这是我最喜欢的话题之一,看到@G.Grothendieck的回答让我非常高兴,因为我钦佩他的学识深度。他的回答比我的更好,因为他使用了问题中提供的数据集作为“挑战”。 - IRTFM

26

poly of a vector x 是指将其中心化后,将其各次幂作为列组成的矩阵进行 QR 分解所得到的结果。例如:

> x<-rnorm(50)
> x0<-sapply(1:5,function(z) x^z)
> x0<-apply(x0,2,function(z) z-mean(z))
> x0<-qr.Q(qr(x0))
> cor(x0,poly(x,5))
                 1             2             3             4             5
[1,] -1.000000e+00 -1.113975e-16 -3.666033e-17  7.605615e-17 -1.395624e-17
[2,] -3.812474e-17  1.000000e+00  1.173755e-16 -1.262333e-17 -3.988085e-17
[3,] -7.543077e-17 -7.778452e-17  1.000000e+00  3.104693e-16 -8.472204e-17
[4,]  1.722929e-17 -1.952572e-16  1.013803e-16 -1.000000e+00 -1.611815e-16
[5,] -5.973583e-17 -1.623762e-18  9.163891e-17 -3.037121e-16  1.000000e+00

1
这个问题可能在数学基础方面比我的答案更“深入”。 - IRTFM
刚注意到有一些符号差异 - 即与poly(x,5)相比,qr.Q(qr(x0))的某些列会出现相反的符号。有什么办法让它们输出相同的符号吗? - Tom Wenseleers

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接