Tại sao có giá trị R ^ 2 (và điều gì đang xác định nó) khi lm không có phương sai trong giá trị dự đoán?


10

Hãy xem xét mã R sau đây:

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)

Nhìn vào http://svn.r-project.org/R/trunk/src/appl/dqrls.f ) không giúp tôi hiểu chuyện gì đang xảy ra, vì tôi không biết Fortran. Trong một câu hỏi khác, người ta đã trả lời rằng các lỗi dung sai của dấu phẩy động là lỗi cho các hệ số của X gần với, nhưng không hoàn toàn bằng 0.

R2 lớn hơn khi giá trị cho coef(example(n))["X"]gần bằng 0. Nhưng ...

  1. Tại sao có giá trị ? R2
  2. Điều gì (cụ thể) là xác định nó?
  3. Tại sao sự tiến bộ dường như có trật tự NaN?
  4. Tại sao vi phạm tiến trình đó?
  5. Hành vi 'mong đợi' này là gì?

Lưu ý: 7 'R ^ 2 phải là 0,4542 để thấy điều gì đó mang tính xây dựng hơn, hãy xem câu trả lời của tôi. :-)

1
Chà, công bằng mà nói, người dùng được cho là thực sự biết điều gì đó về các phương pháp thống kê trước khi sử dụng các công cụ (không giống như người dùng Excel (ok, xin lỗi về ảnh rẻ tiền)). Vì rõ ràng R ^ 2 tiếp cận 1 khi lỗi tiến đến 0, chúng tôi biết rõ hơn là nhầm lẫn giá trị NaN với giới hạn của hàm. Bây giờ, nếu có vấn đề với R ^ 2 chuyển hướng thành ynoise -> 0 (giả sử thay thế câu lệnh Y ở trên bằng Y <- rep(1,n)+runif(n)*ynoise), điều đó sẽ rất thú vị :-)
Carl Witthoft

@eznme: Tôi nghĩ rằng kết quả là cụ thể của máy, hoặc ít nhất là 32 hoặc 64 bit cụ thể; Tôi có một máy 32 bit cho 0,1963 cho 7, nhưng máy 64 bit của tôi cho NaN. Điều thú vị là, trên máy 64 bit, các R ^ 2 không phải là NaN đều rất gần với 0,5. Có ý nghĩa khi tôi nghĩ về nó, nhưng nó làm tôi ngạc nhiên lúc đầu.
Aaron rời khỏi Stack Overflow

1
Bạn đang nghiên cứu lỗi làm tròn chính xác gấp đôi. Hãy nhìn vào các hệ số; ví dụ apply(as.matrix(2:17), 1, function(n){example(n)$coefficients[-1]}). (Kết quả của tôi, trên Win 7 x64 Xeon, dao động từ -8e-17 đến + 3e-16; khoảng một nửa là số không thực.) BTW, nguồn Fortran không giúp ích gì: nó chỉ là một trình bao bọc cho dqrdc; đó là mã bạn muốn xem.
whuber

1
(Tiếp tục) Nhưng, với tư cách là người dùng, việc lựa chọn CV là một trang web tốt hơn, vì lý do đơn giản là phân tích thống kê chuyên sâu là trách nhiệm của người dùng, không phải nhà phát triển. Nếu người dùng thấy sai so với cường độ của RSS, thì họ nên tự xử lý hậu kỳ trước khi báo cáo thêm. Lập trình khôn ngoan, tôi muốn biết làm thế nào để tránh những vấn đề về số này càng nhiều càng tốt, nhưng tôi nghĩ rằng chúng không thể thoát được, và đó là điều quan trọng để có một người dùng siêng năng và giáo dục người khác. R2
Lặp lại

Câu trả lời:


6

Như Ben Bolker nói, câu trả lời cho câu hỏi này có thể được tìm thấy trong mã cho summary.lm().

Đây là tiêu đề:

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

Vì vậy, hãy x <- 1:1000; y <- rep(1,1000); z <- lm(y ~ x)và sau đó hãy xem trích xuất sửa đổi một chút này:

    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)
    }

Lưu ý rằng ans $ r.squared là ...0.4998923

Để trả lời một câu hỏi với một câu hỏi: chúng ta rút ra điều gì từ điều này? :)

Tôi tin rằng câu trả lời nằm ở cách R xử lý các số dấu phẩy động. Tôi nghĩ rằng mssrsslà tổng của các lỗi làm tròn rất nhỏ (bình phương), do đó lý do là khoảng 0,5. Về tiến trình, tôi nghi ngờ điều này có liên quan đến số lượng giá trị cần thiết cho các xấp xỉ +/- để hủy bỏ về 0 (đối với cả hai và , rất có thể là nguồn của các giá trị này ). Tuy nhiên, tôi không biết tại sao các giá trị khác với tiến trình.R2mssrss0/0NaN2^(1:k)


Cập nhật 1: Đây là một chủ đề hay từ R-help giải quyết một số lý do khiến cảnh báo tràn không được giải quyết trong R.

Ngoài ra, SO Q & A này có một số bài viết thú vị và các liên kết hữu ích liên quan đến dòng chảy, số học có độ chính xác cao hơn, v.v.


8

Tôi tò mò về động lực của bạn để đặt câu hỏi. Tôi không thể nghĩ ra một lý do thực tế hành vi này nên quan trọng; trí tò mò trí tuệ là một lý do thay thế (và IMO hợp lý hơn nhiều). Tôi nghĩ bạn không cần phải hiểu FORTRAN để trả lời câu hỏi này, nhưng tôi nghĩ bạn cần biết về phân tách QR và sử dụng nó trong hồi quy tuyến tính. Nếu bạn coi dqrlsnhư một hộp đen tính toán phân tách QR và trả về nhiều thông tin khác nhau, thì bạn có thể theo dõi các bước ... hoặc chỉ cần đi thẳng summary.lmvà theo dõi để xem R ^ 2 được tính như thế nào. Đặc biệt:

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)

Sau đó, bạn phải quay lại lm.fitvà thấy rằng các giá trị được trang bị được tính là r1 <- y - z$residuals(tức là phản hồi trừ đi phần dư). Bây giờ bạn có thể tìm ra cái gì xác định giá trị của phần dư và liệu giá trị trừ đi giá trị trung bình của nó có chính xác bằng 0 hay không, và từ đó tìm ra kết quả tính toán ...


Sự tò mò trí tuệ là phần lớn lý do cho câu hỏi của tôi. Một đồng nghiệp đã báo cáo hành vi và tôi muốn chọc ngoáy và xem liệu tôi có thể tìm ra nó không. Sau khi tôi tìm ra vấn đề ngoài bộ kỹ năng của mình, tôi quyết định đặt câu hỏi. Là một vấn đề thực tế, đôi khi các phân tích được thực hiện theo lô hoặc các lỗi khác xảy ra và hành vi này gây ấn tượng với tôi là 'lẻ'.
russellpierce

1
mms và rss đều là kết quả của z, là tên của đối tượng lm bên trong tóm tắt.lm. Vì vậy, một câu trả lời có thể yêu cầu giải thích về phân tách QR, sử dụng nó trong hồi quy tuyến tính và cụ thể là một số chi tiết phân tách QR được khởi tạo trong mã bên dưới R để giải thích lý do tại sao phân tách QR kết thúc với xấp xỉ 0 thay vì 0 .
russellpierce

@drknexus Tôi không đồng ý. QR decomp là một trong nhiều thuật toán số; nếu vấn đề cơ bản là độ chính xác bằng số, thì vấn đề này sẽ tăng lên trong QR, nhân ma trận, giải quyết phi tuyến tính và rất nhiều nơi khác. Trình tự thiết yếu rất đơn giản: các hệ số tắt rất ít (nên là (0,1)); Điều này không phải là không hợp lý, nhưng tạo ra mssrss"tiếng ồn". Đó là nguyên tắc của GIGO đảm bảo rằng là chính xác, nhưng không chính xác. Tôi thà chèn một "trình phát hiện rác" trước khi tính hơn là sửa đổi thuật toán QR, vì tôi nghi ngờ tính hợp lệ của nó có thể được cải thiện. R2R2
Lặp lại

Dường như với tôi rằng trình phát hiện rác phải ở QR hoặc ngay trước nó. Một kiểm tra độ tỉnh táo đơn giản về phương sai của Y và cảnh báo rằng Y thiếu phương sai sẽ ổn (tôi có thể viết một trình bao bọc lm cho bạn bè của tôi chỉ làm điều này). Dường như với tôi, khi bạn tính , người ta đã đi quá xa lỗ thỏ tính toán để biết liệu người ta có đang nhìn vào rác hay không. R2
russellpierce

0

R2 được định nghĩa là ( http://en.wikipedia.org/wiki/R_squared ), vì vậy nếu tổng bình phương tổng bằng 0 thì không xác định được. Theo tôi R nên hiển thị một thông báo lỗi.R2=1SSerrSStot


1
Bạn có thể đưa ra một tình huống thực tế trong đó hành vi này sẽ có vấn đề?
Ben Bolker

3
@Brandon - Iterator đặt nụ cười vào đó và bạn vẫn còn bất chợt!
Carl Witthoft

2
@eznme Mặc dù một lỗi là tốt, nhưng rất khó để bắt được tất cả các loại nơi phát sinh các vấn đề về dấu phẩy động, đáng chú ý là trong thế giới của số học IEEE-754. Bài học ở đây là ngay cả việc tính toán bánh mì và bơ với R cũng nên được xử lý một cách tinh tế.
Lặp lại

2
Những cân nhắc này đặc biệt quan trọng bởi vì trong các tác phẩm của mình, John Chambers (một trong những người sáng lập ra S và do đó là "ông nội" của R) nhấn mạnh đến việc sử dụng R cho điện toán đáng tin cậy. Ví dụ, xem Chambers, Phần mềm phân tích dữ liệu: Lập trình với R (Springer Verlag 2008): "các tính toán và phần mềm để phân tích dữ liệu nên đáng tin cậy: họ nên làm những gì họ yêu cầu và được nhìn thấy để làm như vậy." [Tại p. 3.]
whuber

2
Vấn đề là dù tốt hơn hay kém hơn, lõi R có khả năng chống lại (như họ thấy), mã này có nhiều mã, nhiều kiểm tra chặn tất cả các trường hợp góc và có thể có lỗi người dùng kỳ lạ - họ sợ (tôi nghĩ) rằng nó sẽ (a) mất một lượng lớn thời gian của họ, (b) làm cho cơ sở mã lớn hơn và khó đọc hơn (bởi vì có hàng ngàn trường hợp đặc biệt này) và (c) làm chậm việc thực thi bằng cách buộc kiểm tra như vậy mọi lúc ngay cả trong các tình huống tính toán đang được lặp đi lặp lại nhiều, nhiều lần.
Ben Bolker
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.