使用 QR 分解在 R 中进行多元回归分析
Multiple regression analysis in R using QR decomposition
我正在尝试编写一个使用 QR 分解求解多元回归的函数。输入:y向量和X矩阵;输出:b、e、R^2。到目前为止,我已经明白了,而且被困住了;我想我把一切都搞得太复杂了:
QR.regression <- function(y, X) {
X <- as.matrix(X)
y <- as.vector(y)
p <- as.integer(ncol(X))
if (is.na(p)) stop("ncol(X) is invalid")
n <- as.integer(nrow(X))
if (is.na(n)) stop("nrow(X) is invalid")
nr <- length(y)
nc <- NCOL(X)
# Householder
for (j in seq_len(nc)) {
id <- seq.int(j, nr)
sigma <- sum(X[id, j]^2)
s <- sqrt(sigma)
diag_ej <- X[j, j]
gamma <- 1.0 / (sigma + abs(s * diag_ej))
kappa <- if (diag_ej < 0) s else -s
X[j,j] <- X[j, j] - kappa
if (j < nc)
for (k in seq.int(j+1, nc)) {
yPrime <- sum(X[id,j] * X[id,k]) * gamma
X[id,k] <- X[id,k] - X[id,j] * yPrime
}
yPrime <- sum(X[id,j] * y[id]) * gamma
y[id] <- y[id] - X[id,j] * yPrime
X[j,j] <- kappa
} # end of Householder transformation
rss <- sum(y[seq.int(nc+1, nr)]^2) # residuals sum of squares
e <- rss/nr
e <- mean(residuals(QR.regression)^2)
beta <- solve(t(X) %*% X, t(X) %*% y)
for (i in seq_len(ncol(X))) # set zeros in the lower triangular side of X
X[seq.int(i+1, nr),i] <- 0
Rsq <- (X[1:nc,1:nc])^2
return(list(Rsq=Rsq, y = y, beta = beta, e = e))
}
UPDATE:
my.QR <- function(y, X) {
X <- as.matrix(X)
y <- as.vector(y)
p <- as.integer(ncol(X))
if (is.na(p)) stop("ncol(X) is invalid")
n <- as.integer(nrow(X))
if (is.na(n)) stop("nrow(X) is invalid")
qr.X <- qr(X)
b <- solve(t(X) %*% X, t(X) %*% y)
e <- as.vector(y - X %*% beta) #e
R2 <- (X[1:p, 1:p])^2
return(list(b = b, e= e, R2 = R2 ))
}
X <- matrix(c(1,2,3,4,5,6), nrow = 2, ncol = 3)
y <- c(1,2,3,4)
my.QR(X, y)
这完全取决于您可以使用多少 R 的内置工具来解决此问题。我已经知道 lm
是不允许的,所以下面是故事的其余部分。
如果允许您使用除lm
以外的任何其他例程
那么您可以简单地使用lm.fit
、.lm.fit
或lsfit
进行基于QR的普通最小二乘法求解。
lm.fit(X, y)
.lm.fit(X, y)
lsfit(X, y, intercept = FALSE)
其中,.lm.fit
最轻,lm.fit
和lsfit
差不多。以下是我们可以通过 .lm.fit
:
做的事情
f1 <- function (X, y) {
z <- .lm.fit(X, y)
RSS <- crossprod(z$residuals)[1]
TSS <- crossprod(y - mean(y))[1]
R2 <- 1 - RSS / TSS
list(coefficients = z$coefficients, residuals = z$residuals, R2 = R2)
}
在你同学的问题中:,我已经用这个来检查SVD方法的正确性
如果不允许使用 R 的内置 QR 分解例程 qr.default
如果.lm.fit
不允许,但是qr.default
可以,那么也没有那么复杂。
f2 <- function (X, y) {
## QR factorization `X = QR`
QR <- qr.default(X)
## After rotation of `X` and `y`, solve upper triangular system `Rb = Q'y`
b <- backsolve(QR$qr, qr.qty(QR, y))
## residuals
e <- as.numeric(y - X %*% b)
## R-squared
RSS <- crossprod(e)[1]
TSS <- crossprod(y - mean(y))[1]
R2 <- 1 - RSS / TSS
## multiple return
list(coefficients = b, residuals = e, R2 = R2)
}
如果您还需要估计系数的方差-协方差,请遵循。
如果你连使用都不允许qr.default
那我们就得自己写QR分解了。 正在给这个。
使用那里的函数myqr
,我们可以写
f3 <- function (X, y) {
## our own QR factorization
## complete Q factor is not required
QR <- myqr(X, complete = FALSE)
Q <- QR$Q
R <- QR$R
## rotation of `y`
Qty <- as.numeric(crossprod(Q, y))
## solving upper triangular system
b <- backsolve(R, Qty)
## residuals
e <- as.numeric(y - X %*% b)
## R-squared
RSS <- crossprod(e)[1]
TSS <- crossprod(y - mean(y))[1]
R2 <- 1 - RSS / TSS
## multiple return
list(coefficients = b, residuals = e, R2 = R2)
}
f3
不是非常有效,因为我们已经明确地形成了 Q
,即使它是 thin-Q
因子。原则上我们应该随着X
的QR分解一起旋转y
,所以不需要形成Q
。
如果您想修复现有代码
这需要一些调试工作,因此需要一些时间。稍后我会再做一个回答。
我正在尝试编写一个使用 QR 分解求解多元回归的函数。输入:y向量和X矩阵;输出:b、e、R^2。到目前为止,我已经明白了,而且被困住了;我想我把一切都搞得太复杂了:
QR.regression <- function(y, X) {
X <- as.matrix(X)
y <- as.vector(y)
p <- as.integer(ncol(X))
if (is.na(p)) stop("ncol(X) is invalid")
n <- as.integer(nrow(X))
if (is.na(n)) stop("nrow(X) is invalid")
nr <- length(y)
nc <- NCOL(X)
# Householder
for (j in seq_len(nc)) {
id <- seq.int(j, nr)
sigma <- sum(X[id, j]^2)
s <- sqrt(sigma)
diag_ej <- X[j, j]
gamma <- 1.0 / (sigma + abs(s * diag_ej))
kappa <- if (diag_ej < 0) s else -s
X[j,j] <- X[j, j] - kappa
if (j < nc)
for (k in seq.int(j+1, nc)) {
yPrime <- sum(X[id,j] * X[id,k]) * gamma
X[id,k] <- X[id,k] - X[id,j] * yPrime
}
yPrime <- sum(X[id,j] * y[id]) * gamma
y[id] <- y[id] - X[id,j] * yPrime
X[j,j] <- kappa
} # end of Householder transformation
rss <- sum(y[seq.int(nc+1, nr)]^2) # residuals sum of squares
e <- rss/nr
e <- mean(residuals(QR.regression)^2)
beta <- solve(t(X) %*% X, t(X) %*% y)
for (i in seq_len(ncol(X))) # set zeros in the lower triangular side of X
X[seq.int(i+1, nr),i] <- 0
Rsq <- (X[1:nc,1:nc])^2
return(list(Rsq=Rsq, y = y, beta = beta, e = e))
}
UPDATE:
my.QR <- function(y, X) {
X <- as.matrix(X)
y <- as.vector(y)
p <- as.integer(ncol(X))
if (is.na(p)) stop("ncol(X) is invalid")
n <- as.integer(nrow(X))
if (is.na(n)) stop("nrow(X) is invalid")
qr.X <- qr(X)
b <- solve(t(X) %*% X, t(X) %*% y)
e <- as.vector(y - X %*% beta) #e
R2 <- (X[1:p, 1:p])^2
return(list(b = b, e= e, R2 = R2 ))
}
X <- matrix(c(1,2,3,4,5,6), nrow = 2, ncol = 3)
y <- c(1,2,3,4)
my.QR(X, y)
这完全取决于您可以使用多少 R 的内置工具来解决此问题。我已经知道 lm
是不允许的,所以下面是故事的其余部分。
如果允许您使用除lm
那么您可以简单地使用lm.fit
、.lm.fit
或lsfit
进行基于QR的普通最小二乘法求解。
lm.fit(X, y)
.lm.fit(X, y)
lsfit(X, y, intercept = FALSE)
其中,.lm.fit
最轻,lm.fit
和lsfit
差不多。以下是我们可以通过 .lm.fit
:
f1 <- function (X, y) {
z <- .lm.fit(X, y)
RSS <- crossprod(z$residuals)[1]
TSS <- crossprod(y - mean(y))[1]
R2 <- 1 - RSS / TSS
list(coefficients = z$coefficients, residuals = z$residuals, R2 = R2)
}
在你同学的问题中:
如果不允许使用 R 的内置 QR 分解例程 qr.default
如果.lm.fit
不允许,但是qr.default
可以,那么也没有那么复杂。
f2 <- function (X, y) {
## QR factorization `X = QR`
QR <- qr.default(X)
## After rotation of `X` and `y`, solve upper triangular system `Rb = Q'y`
b <- backsolve(QR$qr, qr.qty(QR, y))
## residuals
e <- as.numeric(y - X %*% b)
## R-squared
RSS <- crossprod(e)[1]
TSS <- crossprod(y - mean(y))[1]
R2 <- 1 - RSS / TSS
## multiple return
list(coefficients = b, residuals = e, R2 = R2)
}
如果您还需要估计系数的方差-协方差,请遵循
如果你连使用都不允许qr.default
那我们就得自己写QR分解了。
使用那里的函数myqr
,我们可以写
f3 <- function (X, y) {
## our own QR factorization
## complete Q factor is not required
QR <- myqr(X, complete = FALSE)
Q <- QR$Q
R <- QR$R
## rotation of `y`
Qty <- as.numeric(crossprod(Q, y))
## solving upper triangular system
b <- backsolve(R, Qty)
## residuals
e <- as.numeric(y - X %*% b)
## R-squared
RSS <- crossprod(e)[1]
TSS <- crossprod(y - mean(y))[1]
R2 <- 1 - RSS / TSS
## multiple return
list(coefficients = b, residuals = e, R2 = R2)
}
f3
不是非常有效,因为我们已经明确地形成了 Q
,即使它是 thin-Q
因子。原则上我们应该随着X
的QR分解一起旋转y
,所以不需要形成Q
。
如果您想修复现有代码
这需要一些调试工作,因此需要一些时间。稍后我会再做一个回答。