Mặc dù OP chưa hoạt động trong hơn một năm, tôi vẫn quyết định đăng câu trả lời. Tôi sẽ sử dụng X
thay vì S
, như trong thống kê, chúng tôi thường muốn ma trận chiếu trong bối cảnh hồi quy tuyến tính, trong đó X
là ma trận mô hình, y
là vector phản hồi, trong khi H = X(X'X)^{-1}X'
là ma trận mũ/chiếu để Hy
đưa ra giá trị tiên đoán.
Câu trả lời này giả định bối cảnh của các ô vuông nhỏ nhất thông thường. Đối với ô vuông có trọng số tối thiểu, hãy xem Get hat matrix from QR decomposition for weighted least square regression.
Tổng quan
solve
được dựa trên LU thừa số của một ma trận vuông nói chung. Đối với X'X
(nên được tính bằng crossprod(X)
thay vì t(X) %*% X
trong R, đọc ?crossprod
để biết thêm) là đối xứng, chúng tôi có thể sử dụng chol2inv
dựa trên hệ số Choleksy.
Tuy nhiên, hệ số hình tam giác kém ổn định hơn hệ số QR
. Đây không phải là khó hiểu. Nếu X
có số điều kiện kappa
, X'X
sẽ có số có điều kiện kappa^2
. Điều này có thể gây ra khó khăn số lớn. Thông báo lỗi bạn nhận được:
# system is computationally singular: reciprocal condition number = 2.26005e-28
chỉ nói điều này.kappa^2
là khoảng e-28
, nhỏ hơn nhiều so với độ chính xác của máy tại khoảng e-16
. Với dung sai tol = .Machine$double.eps
, X'X
sẽ bị coi là thiếu cấp, do đó hệ số LU và Cholesky sẽ bị hỏng.
Nói chung, chúng tôi chuyển sang SVD hoặc QR trong tình huống này, nhưng xoay vòng Hệ số yếu tố Cholesky là một lựa chọn khác.
- SVD là phương pháp ổn định nhất nhưng quá đắt;
- QR là đáp ứng ổn định, với chi phí tính toán vừa phải và thường được sử dụng trong thực tế;
- Xoay vòng Cholesky nhanh, có độ ổn định chấp nhận được. Đối với ma trận lớn, cái này được ưu tiên.
Sau đây, tôi sẽ giải thích cả ba phương pháp.
Sử dụng QR thừa

Lưu ý rằng ma trận chiếu là hoán vị độc lập, nghĩa là, nó không quan trọng cho dù chúng ta thực hiện QR thừa số có hoặc không xoay vòng.
Trong R, qr.default
có thể gọi thường trình LINPACK DQRDC
cho hệ số QR không được xoay vòng, và LAPACK thường quy DGEQP3
cho hệ số QR của khối được xoay vòng. Hãy tạo ma trận đồ chơi và kiểm tra cả hai tùy chọn:
set.seed(0); X <- matrix(rnorm(50), 10, 5)
qr_linpack <- qr.default(X)
qr_lapack <- qr.default(X, LAPACK = TRUE)
str(qr_linpack)
# List of 4
# $ qr : num [1:10, 1:5] -3.79 -0.0861 0.3509 0.3357 0.1094 ...
# $ rank : int 5
# $ qraux: num [1:5] 1.33 1.37 1.03 1.01 1.15
# $ pivot: int [1:5] 1 2 3 4 5
# - attr(*, "class")= chr "qr"
str(qr_lapack)
# List of 4
# $ qr : num [1:10, 1:5] -3.79 -0.0646 0.2632 0.2518 0.0821 ...
# $ rank : int 5
# $ qraux: num [1:5] 1.33 1.21 1.56 1.36 1.09
# $ pivot: int [1:5] 1 5 2 4 3
# - attr(*, "useLAPACK")= logi TRUE
# - attr(*, "class")= chr "qr"
Lưu ý rằng $pivot
là khác nhau cho hai đối tượng.
Bây giờ, chúng ta định nghĩa một hàm wrapper để tính QQ'
:
f <- function (QR) {
## thin Q-factor
Q <- qr.qy(QR, diag(1, nrow = nrow(QR$qr), ncol = QR$rank))
## QQ'
tcrossprod(Q)
}
Chúng ta sẽ thấy rằng qr_linpack
và qr_lapack
cung cấp cho các ma trận chiếu giống nhau:
H1 <- f(qr_linpack)
H2 <- f(qr_lapack)
mean(abs(H1 - H2))
# [1] 9.530571e-17
Sử dụng phân hủy giá trị đặc biệt

Trong R, svd
tính toán phân tách giá trị ít nhất. Chúng tôi vẫn sử dụng ma trận ví dụ trên X
:
SVD <- svd(X)
str(SVD)
# List of 3
# $ d: num [1:5] 4.321 3.667 2.158 1.904 0.876
# $ u: num [1:10, 1:5] -0.4108 -0.0646 -0.2643 -0.1734 0.1007 ...
# $ v: num [1:5, 1:5] -0.766 0.164 0.176 0.383 -0.457 ...
H3 <- tcrossprod(SVD$u)
mean(abs(H1 - H3))
# [1] 1.311668e-16
Một lần nữa, chúng tôi có cùng ma trận chiếu.
Sử dụng xoay Cholesky thừa

Đối với cuộc biểu tình, chúng tôi vẫn sử dụng ví dụ X
trên.
## pivoted Chol for `X'X`; we want lower triangular factor `L = R'`:
## we also suppress possible rank-deficient warnings (no harm at all!)
L <- t(suppressWarnings(chol(crossprod(X), pivot = TRUE)))
str(L)
# num [1:5, 1:5] 3.79 0.552 -0.82 -1.179 -0.182 ...
# - attr(*, "pivot")= int [1:5] 1 5 2 4 3
# - attr(*, "rank")= int 5
## compute `Q'`
r <- attr(L, "rank")
piv <- attr(L, "pivot")
Qt <- forwardsolve(L, t(X[, piv]), r)
## P = QQ'
H4 <- crossprod(Qt)
## compare
mean(abs(H1 - H4))
# [1] 6.983997e-17
Một lần nữa, chúng tôi có cùng ma trận chiếu.
Có lý do nào khiến bạn không muốn sử dụng princomp hoặc prcomp? Tính toán các thành phần chính không cần phải được thực hiện bằng tay. –
Sợ không có giải pháp chung, nếu đó là số điều kiện bạn gặp sự cố. –
Xin chào, tôi không cố gắng thực hiện PCA nhiều như triển khai một công cụ ước tính mà tôi đã đọc. Tôi thấy nó kỳ lạ mà tôi không thể có được điều này để làm việc ngay cả đối với một ma trận đơn giản của các công cụ giả, khi mà dường như đảm bảo không phải là collinear. – bikeclub