Примітка . Я розмістив розширену версію цієї відповіді на своєму веб-сайті .
Ви б ласкаво розглянути можливість розміщення подібної відповіді з фактичним R-двигуном?
Звичайно! Вниз по кролячій норі ми йдемо.
Перший шар - lm
це інтерфейс, підданий дії програміста R. Ви можете подивитися джерело цього, просто набравши lm
консоль R. Більшість із них (як і більшість більшості кодів виробництва) займається перевіркою входів, встановленням атрибутів об'єкта та викидом помилок; але ця лінія просувається
lm.fit(x, y, offset = offset, singular.ok = singular.ok,
...)
lm.fit
- це ще одна функція R, її можна назвати самостійно. Хоча lm
зручно працювати з формулами та фреймом даних, lm.fit
потрібні матриці, тому цей рівень абстракції видалений. Перевірка джерела на наявність lm.fit
більш зайнятої роботи та наступний дійсно цікавий рядок
z <- .Call(C_Cdqrls, x, y, tol, FALSE)
Зараз ми кудись дістаємось. .Call
- спосіб R ввести код C. У джерелі R десь є функція C, C_Cdqrls, і нам потрібно її знайти. Ось воно .
Знову, дивлячись на функцію C, ми знову виявляємо межі перевірки меж, очищення помилок та напруженої роботи. Але ця лінія інша
F77_CALL(dqrls)(REAL(qr), &n, &p, REAL(y), &ny, &rtol,
REAL(coefficients), REAL(residuals), REAL(effects),
&rank, INTEGER(pivot), REAL(qraux), work);
Отож, зараз ми на своїй третій мові, R назвав C, який закликає фортран. Ось код fortran .
Перший коментар розповідає все це
c dqrfit is a subroutine to compute least squares solutions
c to the system
c
c (1) x * b = y
(що цікаво, схоже, що назва цього розпорядку в певний момент було змінено, але хтось забув оновити коментар). Таким чином, ми нарешті знаходимося в точці, коли ми можемо зробити лінійну алгебру і реально вирішити систему рівнянь. Це така річ, у якій справді хороший фортран, який пояснює, чому ми пройшли через стільки шарів, щоб потрапити сюди.
У коментарі також пояснюється, що збирається робити код
c on return
c
c x contains the output array from dqrdc2.
c namely the qr decomposition of x stored in
c compact form.
Тож fortran збирається вирішити систему, знайшовши розклад .Q R
Перше, що відбувається, і, безумовно, найважливіше, - це
call dqrdc2(x,n,n,p,tol,k,qraux,jpvt,work)
Це викликає функцію fortran dqrdc2
на вхідній матриці x
. Що це?
c dqrfit uses the linpack routines dqrdc and dqrsl.
Отже, ми нарешті домігся до того, щоб розмовити . Лінпак - це бібліотека лінійної алгебри фортрана, яка існує з 70-х років. Більшість серйозних лінійних алгебр в кінцевому підсумку знаходить свій шлях до виправлення. У нашому випадку ми використовуємо функцію dqrdc2
c dqrdc2 uses householder transformations to compute the qr
c factorization of an n by p matrix x.
Тут робиться фактична робота. Мені знадобився б повний повний день, щоб зрозуміти, що робить цей код, він настільки ж низький, як вони приходять. Але загалом у нас є матриця і ми хочемо її розподілити на добуток де - ортогональна матриця, а - верхня трикутна матриця. Це розумно зробити, тому що, маючи і ви можете вирішити лінійні рівняння для регресіїX = Q R Q R Q RХХ= Q RQRQR
ХтХβ= XтY
дуже легко. Справді
ХтХ= RтQтQ R = RтR
так стає вся система
RтR β= RтQту
але є верхнім трикутним і має той же ранг, що і , так що поки наша проблема добре поставлена, вона є повноцінною, і ми можемо просто вирішити скорочену системуX t XRХтХ
R β= Qту
Але ось дивовижна річ. верхній трикутний, тому останнє лінійне рівняння тут просто , тому рішення для тривіальне. Потім ви можете підняти рядки, по черзі, і підміняти в які ви вже знаєте, щоразу отримуючи просте одне змінне лінійне рівняння для вирішення. Отже, як тільки у вас є і , вся справа руйнується до того, що називається зворотною заміною , що легко. Ви можете прочитати про це більш докладно тут , де повністю розроблений явний невеликий приклад.β n β Q RRconstant * beta_n = constant
βнβQR