최소 제곱 법 회귀 단계별 선형 대수 계산


22

R의 선형 혼합 모델에 대한 질문에 대한 전편으로 초보자 / 중급 통계 애호가를위한 참고 자료로 공유하기 위해, 나는 "수동"계산에 관련된 단계를 독립적 인 "Q & A- 스타일"로 게시하기로 결정했습니다. 간단한 선형 회귀의 계수 및 예측 값.

예는 R 내장 데이터 세트를 사용하며 mtcars, 독립 변수 역할을하는 차량이 소비하는 갤런 당 마일로 설정되며, 자동차 무게 (연속 변수) 및 실린더 수에 따라 회귀됩니다. 상호 작용없이 세 가지 수준 (4, 6 또는 8)으로 인수 분해합니다.

편집 :이 질문에 관심이 있다면 CV 외부의 Matthew Drury 가이 게시물 에서 상세하고 만족스러운 답변을 찾을 수 있습니다.


"수동 계산"이라고 말하면 무엇을 찾고 있습니까? (예를 들어, Gram-Schmidt 직교 화 또는 SWEEP 연산자를 통해) 매개 변수 추정값을 얻는 비교적 간단한 일련의 단계를 표시하는 것은 비교적 간단하지만 R이 내부적으로 계산을 수행하는 방식은 아닙니다. 그것 (그리고 대부분의 다른 통계 패키지)은 QR 분해를 사용합니다 (사이트의 여러 게시물에서 논의 됨
-QR

예. 나는 이것이 MD에 의한 답변에서 매우 훌륭하게 해결되었다고 믿는다. 아마도 나의 게시물을 편집해야 할 것이다. 아마도 아마도 내 대답-기둥 공간, 투영 행렬 뒤에 기하학적 접근법을 강조해야 할 것이다.
Antoni Parellada

네! @Matthew Drury OP에서 해당 줄을 지우거나 링크를 업데이트 하시겠습니까?
Antoni Parellada

1
이 링크가 있는지 확실하지 않지만 밀접하게 관련되어 있으며 JM의 답변을 정말 좋아합니다. stats.stackexchange.com/questions/1829/…
Haitao Du

답변:


51

참고 : 내 웹 사이트 에이 답변의 확장 버전을 게시했습니다 .

실제 R 엔진이 노출 된 상태에서 비슷한 답변을 게시 하시겠습니까?

확실한! 토끼 구멍 아래로 내려갑니다.

첫 번째 계층은 lmR 프로그래머에게 노출되는 인터페이스입니다. lmR 콘솔에서 입력하면 소스를 볼 수 있습니다 . 대부분의 프로덕션 레벨 코드와 같은 대부분은 입력 확인, 객체 속성 설정 및 오류 발생으로 바쁩니다. 하지만이 줄은 튀어 나와

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)

이제 우리는 어딘가로 가고 있습니다. .CallR의 C 코드 호출 방식입니다. R 소스에 C_Cdqrls라는 C 함수가 있으며이를 찾아야합니다. 여기 있습니다 .

C 함수를 다시 살펴보면 대부분 범위 검사, 오류 정리 및 작업량이 많은 것을 알 수 있습니다. 하지만이 줄은 다릅니다

F77_CALL(dqrls)(REAL(qr), &n, &p, REAL(y), &ny, &rtol,
        REAL(coefficients), REAL(residuals), REAL(effects),
        &rank, INTEGER(pivot), REAL(qraux), work);

이제 우리는 제 3 언어에 있습니다. R은 포트란을 호출하는 C를 호출했습니다. 포트란 코드는 다음과 같습니다 .

첫 번째 의견은 모든 것을 말해줍니다

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.

따라서 포트란은 분해 를 찾아 시스템을 해결하려고합니다 .아르 자형

가장 먼저 발생하는 일은

call dqrdc2(x,n,n,p,tol,k,qraux,jpvt,work)

dqrdc2입력 행렬 에서 포트란 함수 를 호출합니다 x. 이게 뭐야?

 c     dqrfit uses the linpack routines dqrdc and dqrsl.

그래서 우리는 마침내 linpack 으로 만들었습니다 . Linpack은 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 은 상위 삼각 행렬입니다. QR이 있으면 회귀에 대한 선형 방정식을 풀 수 있기 때문에 이것은 현명한 일입니다.XX=QRQRQR

XtXβ=Xt와이

아주 쉽게. 과연

Xt엑스=아르 자형아르 자형=아르 자형아르 자형

그래서 전체 시스템은

R아르 자형β=아르 자형와이

그러나 은 상부 삼각형이고 X t X 와 같은 순위를 갖습니다 . 따라서 우리의 문제가 잘 제기되는 한, 그것은 전체 순위이며, 우리는 축소 된 시스템을 해결할 수도 있습니다.아르 자형Xt엑스

Rβ=와이

그러나 여기 멋진 것이 있습니다. 은 상부 삼각이므로, 여기서 마지막 선형 방정식은 단지 이므로, β n을 푸는 것은 사소한 것입니다. 그런 다음 행을 하나씩 위로 올라가서 이미 알고 있는 β를 대치 할 때마다 간단한 단일 변수 선형 방정식을 얻을 수 있습니다. 따라서 QR 이 있으면 모든 것이 거꾸로 치환으로 붕괴됩니다 . 명시적인 작은 예제가 완전히 해결 된 여기 에서 더 자세히 읽을 수 있습니다 .아르 자형constant * beta_n = constantββ아르 자형


4
이것은 상상할 수있는 가장 재미있는 수학 / 코딩 짧은 에세이였습니다. 나는 코딩에 대해 아무것도 알지 못하지만 겉보기에 무해한 R 함수의 내장을 통한 당신의 "투어"는 진정으로 눈을 was습니다. 훌륭한 글쓰기! "친절하게"트릭을 수행 한 이후로 ... 문제를 관련 도전으로 친절하게 고려할 수 있습니까? :-)
Antoni Parellada

6
+1 전에 본 적이 없었습니다. 좋은 요약입니다. @Antoni가 가정용 변환에 익숙하지 않은 경우를 대비하여 약간의 정보를 추가하기 만하면됩니다. 본질적으로 선형 변환이므로 이미 처리 한 부분을 올바로 처리하지 않고 (적절한 순서로 수행하는 한) 달성하려는 R 행렬의 한 부분을 제로화 할 수 있습니다. 행렬을 상부 삼각 형태로 변환하기 위해 (Givens 회전은 비슷한 작업을 수행하고 시각화하기는 쉽지만 조금 느립니다). R을 빌드 할 때 동시에 Q
Glen_b -Reinstate Monica를

2
Matthew (+1), 훨씬 자세한 글 madrury.github.io/jekyll/update/2016/07/20/lm-in-R.html에 대한 링크로 게시물을 시작하거나 끝내는 것이 좋습니다 .
아메바는 고

3
기계 코드로 나가지 않고 치킨 아웃하는 경우 -1입니다.
S. Kolassa-복원 Monica Monica

3
(죄송합니다, 농담 ;-)
S. Kolassa-Monica Monica 복원

8

R의 실제 단계별 계산은 Matthew Drury의 답변 에이 같은 스레드에서 아름답게 설명되어 있습니다. 이 답변에서 나는 간단한 예를 가진 R의 결과가 기둥 공간에 대한 투영의 선형 대수와 다른 게시물에 표시된 수직 (점 제품) 오류 개념에 따라 도달 할 수 있음을 스스로 입증하는 과정을 진행하고 싶습니다. Strang 박사는 Linear Algebra와 그 응용 프로그램 에서 잘 설명 하고 있으며 여기에서 쉽게 액세스 할 수 있습니다 .

계수 를 추정하기 위해β

=나는이자형아르 자형기음이자형(기음와이=4)+β1이자형나는h+1나는이자형아르 자형기음이자형(기음와이=6)+2나는이자형아르 자형기음이자형(기음와이=8)[]

12엑스

attach(mtcars)    
x1 <- wt

    x2 <- cyl; x2[x2==4] <- 1; x2[!x2==1] <-0

    x3 <- cyl; x3[x3==6] <- 1; x3[!x3==1] <-0

    x4 <- cyl; x4[x4==8] <- 1; x4[!x4==1] <-0

    X <- cbind(x1, x2, x3, x4)
    colnames(X) <-c('wt','4cyl', '6cyl', '8cyl')

head(X)
        wt 4cyl 6cyl 8cyl
[1,] 2.620    0    1    0
[2,] 2.875    0    1    0
[3,] 2.320    1    0    0
[4,] 3.215    0    1    0
[5,] 3.440    0    0    1
[6,] 3.460    0    1    0

[]lm

β아르 자형영형j에이아르 자형나는엑스=(엑스엑스)1엑스[아르 자형영형j에이아르 자형나는엑스][와이]=[아르 자형이자형아르 자형기음영형이자형에프'에스](엑스엑스)1엑스와이=β

X_tr_X_inv <- solve(t(X) %*% X)    
Proj_M <- X_tr_X_inv %*% t(X)
Proj_M %*% mpg

          [,1]
wt   -3.205613
4cyl 33.990794
6cyl 29.735212
8cyl 27.919934

동일 : coef(lm(mpg ~ wt + as.factor(cyl)-1)).

H에이에이아르 자형나는엑스=엑스(엑스엑스)1엑스

HAT <- X %*% X_tr_X_inv %*% t(X)

와이^엑스(엑스엑스)1엑스와이y_hat <- HAT %*% mpg

cyl <- as.factor(cyl); OLS <- lm(mpg ~ wt + cyl); predict(OLS):

y_hat <- as.numeric(y_hat)
predicted <- as.numeric(predict(OLS))
all.equal(y_hat,predicted)
[1] TRUE

1
일반적으로 수치 계산에서는 역행렬을 계산하는 대신 선형 방정식을 푸는 것이 가장 좋습니다. 따라서 beta = solve(t(X) %*% X, t(X) %*% y)실제로는보다 정확 하다고 생각 solve(t(X) %*% X) %*% t(X) %*% y합니다.
Matthew Drury

R은 그렇게하지 않습니다-QR 분해를 사용합니다. 당신이 설명하기 위하여려고하는 경우에 알고리즘을 컴퓨터에서 사용을 나는 의심 사람이 당신이 보여 하나를 사용합니다.
복원 Monica Monica-G. Simpson

알고리즘 이후가 아니라 선형 대수적 토대를 이해하려고합니다.
Antoni Parellada

@AntoniParellada이 경우에도 많은 상황에서 선형 방정식에 대한 생각이 여전히 더 밝아졌습니다.
Matthew Drury

1
이 스레드와 사이트의 목표와의 주변 관계를 고려할 때 R중요한 계산 에 대한 사용법을 설명하는 가치를 보면서 이를 블로그에 기여하도록
whuber
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.