2016-04-09 3 views
1

Я не могу найти документацию относительно точной работы этой функции. У меня есть QR-разложение матрицы X:`qr.qy()` function in R

X = matrix(c(1,1,1,1,-1.5,-0.5,0.5,1.5,2.25,0.25,0.25, 2.25,-3.275,-0.125,0.125,3.375), 
nrow=4, byrow=F) 

    [,1] [,2] [,3] [,4] 
[1,] 1 -1.5 2.25 -3.375 
[2,] 1 -0.5 0.25 -0.125 
[3,] 1 0.5 0.25 0.125 
[4,] 1 1.5 2.25 3.375 

Функция qr(X) дает список:

$qr (rounding output) 
    [,1]  [,2]   [,3]   [,4] 
[1,] -2.0   0   -2.5    0 
[2,] 0.5  -2.236    0  -4.583 
[3,] 0.5  0.447    2    0 
[4,] 0.5  0.894  -0.929  -1.341 

$rank 
[1] 4 

$qraux 
[1] 1.500000 1.000000 1.368524 1.341641 

$pivot 
[1] 1 2 3 4 

attr(,"class") 
[1] "qr" 

я выбираю диагональные элементы qr(X)$qr, которые я называю z:

z = qr(X)$qr 
z = Q * (row(Q) == col(Q)) 

    [,1]  [,2] [,3]  [,4] 
[1,] -2 0.000000 0 0.000000 
[2,] 0 -2.236068 0 0.000000 
[3,] 0 0.000000 2 0.000000 
[4,] 0 0.000000 0 -1.341641 

Пока, так хорошо. Теперь следующий звонок я не понимаю:

(raw = qr.qy(qr(X), z)) 

    [,1] [,2] [,3] [,4] 
[1,] 1 -1.5 1 -0.3 
[2,] 1 -0.5 -1 0.9 
[3,] 1 0.5 -1 -0.9 
[4,] 1 1.5 1 0.3 

некоторый прогресс:

Таким образом, благодаря ответу и некоторые чтение, я думаю, что объект qr(X)$qr содержит R полностью в верхнем треугольник:

 [,1]  [,2]   [,3]   [,4] 
[1,] -2.0   0   -2.5    0 
[2,]   -2.236    0  -4.583 
[3,]        2    0 
[4,]          -1.341 

нижний треугольник qr(X)$qr содержит информацию о Q:

 [,1]  [,2]   [,3]   [,4] 
[1,]            
[2,] 0.5          
[3,] 0.5  0.447        
[4,] 0.5  0.894  -0.929  

Как-то вызов qr.Q(qr(X)) возвращает Q, используя внутреннюю функцию qr.qy() с qr() и диагональной матрицей 1 в качестве входных данных.

Но как осуществляется эта операция? Как заполняется остальная часть верхнего верхнего угла Q? Я думаю, что он использует $qraux, но как ему добраться до:

 [,1]  [,2] [,3]  [,4] 
[1,] -0.5 0.6708204 0.5 0.2236068 
[2,] -0.5 0.2236068 -0.5 -0.6708204 
[3,] -0.5 -0.2236068 -0.5 0.6708204 
[4,] -0.5 -0.6708204 0.5 -0.2236068 

Короче, Как qr.qy() работает конкретно?

Я только что нашел это: «qy.qr(): возвращает результаты умножения матрицы: Q% *% y, где Q - ортогональное (или унитарное) преобразование порядка (x), представленное qr «.

+0

Вы, кажется, думаете, что матрица 'qr (X) $ qr' является матрицей' Q'. Это не. Это компактное представление Q-матрицы. Если вы хотите, чтобы фактическая Q-матрица использовала функцию 'qr.Q'. См. Документацию; есть ссылка на 'qr.Q' на странице справки для функции' qr'. Просто сделайте 'Q <- qr.Q (qr (X))' вместо того, что вы делаете, а затем выполните 'Q% *% z'. – Bhas

+0

Нет, он не генерирует 'Q'. Он использует специальные процедуры lapack для выполнения умножения без генерации явного 'Q'. – Bhas

+0

Спасибо. Поэтому, когда вы говорите, что он не генерирует Q, вы имеете в виду, что 'qr.qy()' не генерирует Q, правильно? Так что это вообще обход Q, но результат после умножения Q и z идентичен, как если бы он использовал Q? Есть ли способ убедить вас написать официальный ответ? – Toni

ответ

4

Матрица Q из QR-разложения является только неявной в возвращаемом значении функции qr. Элемент списка qr является компактным представлением Q-матрицы; содержится в нижней треугольной части элемента списка qr и в векторе qraux. Верхняя треугольная матрица R QR-декомпозиции представляет собой верхнюю треугольную часть элемента списка qr в возвращаемом значении.

Функция R qr.qy после некоторых промежуточных шагов в конечном итоге вызывает подпрограмму Lapack dormqr, которая НЕ генерирует матрицу Q явно. Он использует информацию, содержащуюся в элементах списка qr и qraux. См. http://www.netlib.org/lapack/explore-html/da/d82/dormqr_8f.html.

Так qr.qy НЕ преобразует компактную форму Q в фактический Q. Он использует компактную форму для вычисления Q %*% z.

Функция R qr.Q (что вы сделали) использует qr.qy с диагональной матрицей с 1 на диагоналях для генерации Q.

Почему это делается так? По соображениям эффективности.

С помощью следующего кода вы можете проверить это:

library(rbenchmark) 

benchmark(qr.qy(XQR,z), {Q <- qr.Q(qr(X)); Q %*% z}, { Q %*% z}, 
      replications=10000, 
      columns=c("test","replications","elapsed","relative") ) 

с выходом

         test replications elapsed relative 
3       { Q %*% z}  10000 0.022 1.000 
2  { Q <- qr.Q(qr(X)); Q %*% z}  10000 0.486 22.091 
1       qr.qy(XQR, z)  10000 0.152 6.909 

Урок: только генерировать Q, если это действительно необходимо в явном виде, и если вам нужно создать его много с разными входными матрицами. Если Q исправлена ​​и не изменяется, то вы можете использовать Q %*% z.

+0

+1 Большое спасибо. Я не понимал, что вы пошли вперед и ответили на мой вопрос. У вас возникли какие-либо ссылки или, возможно, некоторые дополнительные слова ... Я очень стараюсь выяснить, как создать эту «компактную Q» матрицу. – Toni

+0

Например, мне интересно, если [эта книга] (https://books.google.com/books?id=iIOhAwAAQBAJ&pg=PA241&lpg=PA241&dq= linear+algebra+and+matrix+analysis+for+statistics+reflectors&source=bl&ots= eZDhKU8BJO & sig = MPCJuWXpWSBJC9_ohHBI6UX-xJ0 & hl = en & sa = X & ved = 0ahUKEwjshNX9p4XMAhUEVT4KHRzkDPQQ6AEIMTAD # v = onepage & q = reflectors & f = false) содержит хорошее объяснение этих «рефлекторов» ... – Toni

+0

Например, и только для того, чтобы сфокусировать свое исследование, это любая из матриц (T или V, ...) упомянули [здесь] (http://www.netlib.org/lapack/lug/node69.html) «компактную форму», на которую вы ссылаетесь. Ссылка, которую вы включаете, настолько тяжелая, что я не могу следовать. – Toni