Почему существует значение R ^ 2 (и что его определяет), когда lm не имеет дисперсии в прогнозируемом значении?

10

Рассмотрим следующий код 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 ) не помог мне понять, что происходит, потому что я не знаю Фортрана. В другом вопросе ответили, что ошибки допусков машин с плавающей запятой были виноваты в коэффициентах для X, которые близки, но не совсем равны 0.

больше, когда значение дляближе к 0. Но ...R2coef(example(n))["X"]

  1. Почему значение вообще? R2
  2. Что (конкретно) это определяет?
  3. Почему, казалось бы, упорядоченная прогрессия NaNрезультатов?
  4. Почему нарушения этой прогрессии?
  5. Что из этого является «ожидаемым» поведением?
russellpierce
источник
Примечание: R 7 для 7 должно быть 0,4542, чтобы увидеть что-то более конструктивное, см. Мой ответ. :-)
1
Ну, честно говоря, пользователь должен знать кое-что о статистических методах, прежде чем использовать инструменты (в отличие, скажем, от пользователей Excel (хорошо, извините за дешевый выстрел)). Поскольку довольно очевидно, что R ^ 2 приближается к 1, когда ошибка приближается к нулю, мы знаем лучше, чем путать значение NaN с пределом функции. Теперь, если бы была проблема с R ^ 2, расходящимся как ynoise -> 0 (скажем, заменим Y оператор выше на Y <- rep(1,n)+runif(n)*ynoise), это было бы интересно :-)
Carl Witthoft
@eznme: Я думаю, что результаты зависят от конкретной машины или, по крайней мере, от 32 до 64 бит; У меня есть 32-битная машина, которая дает 0.1963 для 7, но моя 64-битная машина дает NaN. Интересно, что на 64-битной машине R ^ 2, которые не являются NaN, очень близки к 0,5. Имеет смысл, когда я думаю об этом, но сначала это удивляет меня.
Аарон оставил переполнение стека
1
Вы изучаете ошибку округления двойной точности. Посмотрите на коэффициенты; например, apply(as.matrix(2:17), 1, function(n){example(n)$coefficients[-1]}). (Мои результаты на Win 7 x64 Xeon варьируются от -8e-17 до + 3e-16; около половины - истинные нули.) Кстати, источник на Фортране не поможет: это просто оболочка для dqrdc; это код, который вы хотите посмотреть.
whuber
1
R2

Ответы:

6

Как говорит Бен Болкер, ответ на этот вопрос можно найти в коде для 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)
    }

0.4998923

Чтобы ответить на вопрос вопросом: что мы из этого получаем? :)

mssrssR2mssrss0/0NaN2^(1:k)


Обновление 1: Вот хорошая ветка из R-help, в которой рассматриваются некоторые причины, по которым предупреждения о недостаточном объеме не рассматриваются в R.

Кроме того, в этом разделе «Вопросы и ответы» есть ряд интересных постов и полезных ссылок, касающихся недостаточного значения, арифметики высокой точности и т. Д.

Итератор
источник
8

Мне интересно, какая у вас мотивация задать вопрос. Я не могу думать о практической причине, это поведение должно иметь значение; Интеллектуальное любопытство является альтернативой (и 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(т.е. как ответ за вычетом остатков). Теперь вы можете выяснить, что определяет значение невязок, и является ли значение минус среднее значение точно нулевым или нет, и оттуда выяснить результаты вычислений ...

Бен Болкер
источник
Интеллектуальное любопытство - основная причина моего вопроса. Коллега сообщил о поведении, и я хотел осмотреться и посмотреть, смогу ли я это выяснить. После того, как я отследил проблему за пределами моего набора навыков, я решил задать вопрос. Как практическая проблема, иногда анализ выполняется партиями, или возникают другие ошибки, и такое поведение кажется мне совершенно «странным».
russellpierce
1
mms и rss оба являются результатами z, который является именем объекта lm внутри summary.lm. Таким образом, ответ, вероятно, требует объяснения QR-декомпозиции, его использования в линейной регрессии и, в частности, некоторых деталей QR-декомпозиции, как показано в коде, лежащем в основе R, чтобы объяснить, почему QR-декомпозиция заканчивается с приближениями 0, а не 0 самого ,
russellpierce
mssrssR2R2
R2
0

R2R2=1SSerrSStot

Бернд Элькеманн
источник
1
Можете ли вы привести практическую ситуацию, когда это поведение будет иметь значение?
Бен Болкер
3
@ Брэндон - Итератор поместил смайлик туда, и ты все еще получил свист!
Карл Виттофт
2
@eznme Несмотря на то, что ошибка является хорошей, довольно трудно отследить все виды мест, где возникают проблемы с плавающей запятой, особенно в мире арифметики IEEE-754. Урок здесь заключается в том, что даже вычисления с использованием R и хлеба с маслом должны выполняться деликатно.
Итератор
2
Эти соображения особенно важны, потому что в своих работах Джон Чэмберс (один из создателей S и, следовательно, «дедушка» R) настоятельно подчеркивает использование R для надежных вычислений. Например, см. Chambers, Программное обеспечение для анализа данных: программирование на R (Springer Verlag 2008): «Вычисления и программное обеспечение для анализа данных должны быть заслуживающими доверия: они должны делать то, что заявляют, и должны это делать». [На стр. 3.]
whuber
2
Проблема в том, что, к лучшему или к худшему, R-ядро устойчиво (как они это видят) к тому, чтобы усыпить код множеством проверок, которые пересекают все угловые случаи и возможные странные ошибки пользователя - они боятся (я думаю), что это (а) потребует огромного количества времени, (б) сделает базу кода намного больше и труднее для чтения (потому что буквально тысячи таких особых случаев), и (в) замедлит выполнение, заставляя такие проверки все время даже в ситуациях, когда вычисления повторяются много, много раз.
Бен Болкер