Không có câu trả lời nào cho đến nay đã chỉ đúng hướng.
Câu trả lời được chấp nhận bởi @idr đang gây nhầm lẫn giữa lm
và summary.lm
. lm
không tính thống kê chẩn đoán ở tất cả; thay vào đó, summary.lm
. Vì vậy, ông đang nói về summary.lm
.
@Jake 's câu trả lời là một thực tế về sự ổn định số của yếu tố QR và hệ số LU/Choleksy. Câu trả lời của Aravindakshan mở rộng điều này, bằng cách chỉ ra số lượng các hoạt động điểm nổi phía sau cả hai hoạt động (mặc dù như ông nói, ông không tính vào chi phí cho sản phẩm ma trận chéo máy tính). Nhưng, đừng nhầm lẫn số lượng FLOP với chi phí bộ nhớ. Trên thực tế cả hai phương pháp có cùng một bộ nhớ sử dụng trong LINPACK/LAPACK. Cụ thể, lập luận của ông rằng phương pháp QR tốn nhiều RAM hơn để lưu trữ Q
là yếu tố không có thật. Dung lượng được nén như được giải thích trong lm(): What is qraux returned by QR decomposition in LINPACK/LAPACK làm rõ cách tính và lưu trữ hệ số QR. Vấn đề tốc độ của v.v. Chol được nêu chi tiết trong câu trả lời của tôi: Why the built-in lm function is so slow in R? và câu trả lời của tôi trên faster lm
cung cấp một thói quen nhỏ lm.chol
sử dụng phương pháp Choleksy, nhanh gấp 3 lần phương pháp QR.
@Greg câu trả lời/đề xuất cho biglm
là tốt, nhưng nó không trả lời câu hỏi. Vì biglm
được đề cập, tôi sẽ chỉ ra rằng QR decomposition differs in lm
and biglm
. biglm
tính toán sự phản ánh của chủ hộ sao cho hệ số R
kết quả có đường chéo tích cực. Xem Cholesky factor via QR factorization để biết chi tiết. Lý do mà biglm
thực hiện điều này, là kết quả R
sẽ giống như yếu tố Cholesky, xem QR decomposition and Choleski decomposition in R để biết thông tin. Ngoài ra, ngoài biglm
, bạn có thể sử dụng mgcv
. Đọc câu trả lời của tôi: biglm
predict unable to allocate a vector of size xx.x MB để biết thêm.
Sau một Tóm lại, đó là thời gian để gửi câu trả lời của tôi.
Để phù hợp với một mô hình tuyến tính, lm
sẽ
- tạo ra một khung mô hình;
- tạo ma trận mô hình;
- gọi
lm.fit
để xác thực QR;
- trả lại kết quả của hệ số QR cũng như khung mô hình trong
lmObject
.
Bạn đã nói khung dữ liệu đầu vào của mình với 5 cột có giá 2 GB để lưu trữ. Với 20 mức độ yếu tố, ma trận mô hình kết quả có khoảng 25 cột lấy 10 GB dung lượng lưu trữ. Bây giờ chúng ta hãy xem cách sử dụng bộ nhớ tăng lên khi chúng ta gọi lm
.
- [môi trường toàn cầu] ban đầu bạn có bộ nhớ 2 GB cho khung dữ liệu;
- [
lm
envrionment] sau đó nó được sao chép vào khung mô hình, chi phí 2 GB;
- [
lm
môi trường] thì ma trận mô hình được tạo, chi phí 10 GB;
- [
lm.fit
môi trường] bản sao ma trận mô hình được tạo sau đó được ghi đè bằng hệ số QR, chi phí 10 GB;
- [
lm
môi trường] kết quả của lm.fit
được trả lại, chi phí 10 GB;
- [môi trường toàn cầu] kết quả của
lm.fit
được trả lại thêm bởi lm
, chi phí 10 GB khác;
- [môi trường toàn cầu] khung mô hình được trả về
lm
, chi phí 2 GB.
Vì vậy, tổng số RAM 46 GB là cần thiết, lớn hơn nhiều so với RAM 22 GB có sẵn của bạn.
Thực tế nếu lm.fit
có thể được "gạch chân" thành lm
, chúng tôi có thể tiết kiệm 20 GB chi phí. Nhưng không có cách nào để inline một hàm R trong hàm R khác.
Có lẽ chúng ta có thể lấy một ví dụ nhỏ để xem những gì xảy ra xung quanh lm.fit
:
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
Vì vậy, trên thực tế, X
được sao chép khi truyền vào lm.fit
. Chúng ta hãy có một cái nhìn vào những gì qrfit
có
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
Lưu ý rằng QR ma trận nhỏ gọn qrfit$qr$qr
là lớn như mô hình ma trận X
. Nó được tạo ra bên trong lm.fit
, nhưng trên lối ra của lm.fit
, nó được sao chép. Vì vậy, tổng cộng, chúng tôi sẽ có 3 "bản sao" của X
:
- nguyên bản trong môi trường toàn cầu;
- ảnh được sao chép vào
lm.fit
, ghi đè bằng hệ số QR;
- số được trả về
lm.fit
.
Trong trường hợp của bạn, X
là 10 GB, vì vậy chi phí bộ nhớ được kết hợp với riêng lm.fit
đã là 30 GB. Hãy để một mình chi phí khác liên quan đến lm
.
Mặt khác, chúng ta hãy có một cái nhìn tại
solve(crossprod(X), crossprod(X,y))
X
mất 10 GB, nhưng crossprod(X)
chỉ là một ma trận 25 * 25
, và crossprod(X,y)
chỉ là một vector chiều dài-25. Chúng quá nhỏ so với X
, do đó việc sử dụng bộ nhớ không tăng chút nào.
Có thể bạn đang lo lắng rằng một bản sao cục bộ của X
sẽ được thực hiện khi gọi crossprod
? Không có gì! Không giống như lm.fit
thực hiện cả việc đọc và ghi thành X
, crossprod
chỉ đọc X
, do đó không sao chép được thực hiện. Chúng tôi có thể xác minh điều này với ma trận đồ chơi của chúng tôi X
bởi:
tracemem(X)
crossprod(X)
Bạn sẽ không thấy thông báo sao chép!
Nếu bạn muốn có một bản tóm tắt ngắn cho tất cả ở trên, ở đây là:
- chi phí bộ nhớ cho
lm.fit(X, y)
(hoặc thậm chí .lm.fit(X, y)
) là ba lần lớn như rằng cho solve(crossprod(X), crossprod(X,y))
;
- Tùy thuộc vào ma trận mô hình lớn hơn khung mô hình, chi phí bộ nhớ cho
lm
lớn gấp 3 ~ 6 lần đối với solve(crossprod(X), crossprod(X,y))
. Giới hạn dưới 3 không bao giờ đạt được, trong khi ngưỡng trên 6 đạt được khi ma trận mô hình giống như khung mô hình. Đây là trường hợp khi không có biến yếu tố hoặc các điều khoản "yếu tố-như nhau", như bs()
và poly()
vv
lý do tại sao bạn không thử 'lm.fit' thay vì 'lm' để thu hẹp vấn đề? 'lm.fit' chỉ thực hiện mô hình tuyến tính" thô "nhiều hơn hoặc ít hơn phù hợp thông qua phân tích QR - không có công cụ không liên quan nào về tạo ma trận mô hình, v.v. Nếu bạn gặp vấn đề về bộ nhớ với' lm.fit', sau đó câu trả lời của @ Jake có vẻ là vấn đề (QR vs phương trình bình thường). –