R 为什么lm会耗尽内存,而矩阵乘法可以很好地处理系数?
我正在尝试用R做固定效应线性回归R 为什么lm会耗尽内存,而矩阵乘法可以很好地处理系数?,r,memory,regression,linear-regression,lm,R,Memory,Regression,Linear Regression,Lm,我正在尝试用R做固定效应线性回归 dte yr id v1 v2 . . . . . . . . . . . . . . . 然后,我决定简单地将yr作为一个因子,并使用lm: lm(v1 ~ factor(yr) + v2 - 1, data = df) 然而,这似乎耗尽了内存。我的因子中有20个级别,df是1400万行,存储大约需要2GB,我在一台22 GB的机器上运行这个过程 然后我决定
dte yr id v1 v2
. . . . .
. . . . .
. . . . .
然后,我决定简单地将yr
作为一个因子,并使用lm
:
lm(v1 ~ factor(yr) + v2 - 1, data = df)
然而,这似乎耗尽了内存。我的因子中有20个级别,df
是1400万行,存储大约需要2GB,我在一台22 GB的机器上运行这个过程
然后我决定用老式的方法来尝试:为我的每一年t1
到t20
创建虚拟变量,方法是:
df$t1 <- 1*(df$yr==1)
df$t2 <- 1*(df$yr==2)
df$t3 <- 1*(df$yr==3)
...
这运行起来没有问题,并且几乎可以立即得到答案
我特别好奇的是,当我可以很好地计算系数时,lm是什么导致它的内存不足?谢谢。
lm
所做的不仅仅是为您的输入功能查找系数。例如,它提供诊断统计信息,告诉您有关自变量系数的更多信息,包括每个自变量的标准误差和t值
我认为,在运行回归时,了解这些诊断统计数据对于了解回归的有效性非常重要
这些额外的计算导致lm
比简单地求解回归矩阵方程要慢
例如,使用mtcars
数据集:
>data(mtcars)
>lm_cars <- lm(mpg~., data=mtcars)
>summary(lm_cars)
Call:
lm(formula = mpg ~ ., data = mtcars)
Residuals:
Min 1Q Median 3Q Max
-3.4506 -1.6044 -0.1196 1.2193 4.6271
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 12.30337 18.71788 0.657 0.5181
cyl -0.11144 1.04502 -0.107 0.9161
disp 0.01334 0.01786 0.747 0.4635
hp -0.02148 0.02177 -0.987 0.3350
drat 0.78711 1.63537 0.481 0.6353
wt -3.71530 1.89441 -1.961 0.0633 .
qsec 0.82104 0.73084 1.123 0.2739
vs 0.31776 2.10451 0.151 0.8814
am 2.52023 2.05665 1.225 0.2340
gear 0.65541 1.49326 0.439 0.6652
carb -0.19942 0.82875 -0.241 0.8122
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 2.65 on 21 degrees of freedom
Multiple R-squared: 0.869, Adjusted R-squared: 0.8066
F-statistic: 13.93 on 10 and 21 DF, p-value: 3.793e-07
>数据(mtcars)
>lm_车辆摘要(lm_车辆)
电话:
lm(公式=mpg~,数据=mtcars)
残差:
最小1季度中值3季度最大值
-3.4506 -1.6044 -0.1196 1.2193 4.6271
系数:
估计标准误差t值Pr(>t)
(截距)12.30337 18.71788 0.657 0.5181
气缸-0.11144 1.04502-0.107 0.9161
显示0.01334 0.01786 0.747 0.4635
hp-0.02148 0.02177-0.987 0.3350
drat 0.78711 1.63537 0.481 0.6353
wt-3.71530 1.89441-1.961 0.0633。
qsec 0.82104 0.73084 1.123 0.2739
对0.31776 2.10451 0.151 0.8814
am 2.52023 2.05665 1.225 0.2340
档位0.65541 1.49326 0.439 0.6652
碳水化合物-0.19942 0.82875-0.241 0.8122
---
签名。代码:0'***'0.001'***'0.01'*'0.05'.'0.1''1
剩余标准误差:21个自由度上的2.65
倍数R平方:0.869,调整后的R平方:0.8066
F-统计量:10和21 DF上的13.93,p-值:3.793e-07
除了idris所说的之外,还值得指出的是,lm()并不像您在问题中所说明的那样,使用正规方程求解参数,而是使用QR分解,它的效率较低,但往往会产生更精确的数值解。 < P>你可能想考虑使用这个包。它通过使用较小的数据块来适应lm模型 详细阐述杰克的观点。假设您的回归正试图解决:y=Ax
(A是设计矩阵)。对于m个观测值和n个自变量,A是一个mxn矩阵。那么QR的成本是~m*n^2
。在您的例子中,它看起来像m=14x10^6和n=20。因此,m*n^2=14*10^6*400
是一个巨大的成本
然而,对于正态方程,您正试图反转A'A
('表示转置),它是正方形,大小为nxn
。通常使用LU进行求解,其成本n^3=8000
。这比QR的计算成本要小得多当然,这不包括矩阵乘法的成本。
此外,如果QR例程尝试存储大小为
mxm=14^2*10^12(!)的Q矩阵,则您的内存将不足。
写入QR可能不会出现此问题。了解QR的实际使用版本会很有趣。以及为什么lm
调用内存不足。到目前为止,没有一个答案指向正确的方向
被接受的答案是混淆了lm
和summary.lm
lm
根本不计算诊断统计数据;相反,summary.lm
。所以他说的是summary.lm
他的答案是关于QR分解和LU/Choleksy分解的数值稳定性的事实s的回答对此进行了扩展,指出了这两种操作背后的浮点运算量(尽管正如他所说,他没有计算矩阵叉积的成本)。但是,不要混淆触发器计数和内存成本。实际上,这两种方法在LINPACK/LAPACK中具有相同的内存使用率。具体来说,他认为QR方法存储Q
因子需要更多RAM的观点是错误的。中解释的压缩存储澄清了如何计算和存储QR因子分解。QR v.s.Chol的速度问题在我的回答中有详细说明:,我在上的回答提供了一个使用Choleksy方法的小程序lm.Chol
,比QR方法快3倍
对于biglm
的回答/建议是好的,但它没有回答这个问题。既然提到了biglm
,我想指出这一点biglm
计算householder反射,从而得到的R
因子具有正对角线。有关详细信息,请参阅。biglm
这样做的原因是得到的R
wil
>data(mtcars)
>lm_cars <- lm(mpg~., data=mtcars)
>summary(lm_cars)
Call:
lm(formula = mpg ~ ., data = mtcars)
Residuals:
Min 1Q Median 3Q Max
-3.4506 -1.6044 -0.1196 1.2193 4.6271
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 12.30337 18.71788 0.657 0.5181
cyl -0.11144 1.04502 -0.107 0.9161
disp 0.01334 0.01786 0.747 0.4635
hp -0.02148 0.02177 -0.987 0.3350
drat 0.78711 1.63537 0.481 0.6353
wt -3.71530 1.89441 -1.961 0.0633 .
qsec 0.82104 0.73084 1.123 0.2739
vs 0.31776 2.10451 0.151 0.8814
am 2.52023 2.05665 1.225 0.2340
gear 0.65541 1.49326 0.439 0.6652
carb -0.19942 0.82875 -0.241 0.8122
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 2.65 on 21 degrees of freedom
Multiple R-squared: 0.869, Adjusted R-squared: 0.8066
F-statistic: 13.93 on 10 and 21 DF, p-value: 3.793e-07
X <- matrix(rnorm(30), 10, 3) # a `10 * 3` model matrix
y <- rnorm(10) ## response vector
tracemem(X)
# [1] "<0xa5e5ed0>"
qrfit <- lm.fit(X, y)
# tracemem[0xa5e5ed0 -> 0xa1fba88]: lm.fit
str(qrfit)
#List of 8
# $ coefficients : Named num [1:3] 0.164 0.716 -0.912
# ..- attr(*, "names")= chr [1:3] "x1" "x2" "x3"
# $ residuals : num [1:10] 0.4 -0.251 0.8 -0.966 -0.186 ...
# $ effects : Named num [1:10] -1.172 0.169 1.421 -1.307 -0.432 ...
# ..- attr(*, "names")= chr [1:10] "x1" "x2" "x3" "" ...
# $ rank : int 3
# $ fitted.values: num [1:10] -0.466 -0.449 -0.262 -1.236 0.578 ...
# $ assign : NULL
# $ qr :List of 5
# ..$ qr : num [1:10, 1:3] -1.838 -0.23 0.204 -0.199 0.647 ...
# ..$ qraux: num [1:3] 1.13 1.12 1.4
# ..$ pivot: int [1:3] 1 2 3
# ..$ tol : num 1e-07
# ..$ rank : int 3
# ..- attr(*, "class")= chr "qr"
# $ df.residual : int 7
solve(crossprod(X), crossprod(X,y))
tracemem(X)
crossprod(X)