De hecho, generalizar esta receta a GLM no es difícil, ya que los GLM generalmente se ajustan utilizando mínimos cuadrados repesados de forma iterativa . Por lo tanto, dentro de cada iteración, se puede sustituir el paso regular de mínimos cuadrados ponderados con un paso de mínimos cuadrados ponderado de cresta para obtener un GLM penalizado de cresta. De hecho, en combinación con penalizaciones de cresta adaptativa, esta receta se utiliza para ajustar GLM penalizados L0 (también conocido como el mejor subconjunto, es decir, GLM donde se penaliza el número total de coeficientes distintos de cero). Esto se ha implementado, por ejemplo, en el paquete l0ara , consulte este documento y este para obtener más detalles.
También vale la pena señalar que la forma más rápida de resolver una regresión de cresta regular es usar
lmridge_solve = function (X, y, lambda, intercept = TRUE) {
if (intercept) {
lambdas = c(0, rep(lambda, ncol(X)))
X = cbind(1, X)
} else { lambdas = rep(lambda, ncol(X)) }
solve(crossprod(X) + diag(lambdas), crossprod(X, y))[, 1]
}
para el caso donde n>=p
, o usando
lmridge_solve_largep = function (X, Y, lambda) (t(X) %*% solve(tcrossprod(X)+lambda*diag(nrow(X)), Y))[,1]
cuando p>n
y para un modelo sin intercepción.
Esto es más rápido que usar la receta de aumento de filas , es decir, hacer
lmridge_rbind = function (X, y, lambda, intercept = TRUE) {
if (intercept) {
lambdas = c(0, rep(lambda, ncol(X)))
X = cbind(1, X)
} else { lambdas = rep(lambda, ncol(X)) }
qr.solve(rbind(X, diag(sqrt(lambdas))), c(y, rep(0, ncol(X))))
}
Si resulta que necesita restricciones de no negatividad en sus coeficientes ajustados, entonces simplemente puede hacer
library(nnls)
nnlmridge_solve = function (X, y, lambda, intercept = TRUE) {
if (intercept) {
lambdas = c(0, rep(lambda, ncol(X)))
X = cbind(1, X)
} else { lambdas = rep(lambda, ncol(X)) }
nnls(A=crossprod(X)+diag(lambdas), b=crossprod(X,Y))$x
}
que luego da un resultado un poco más preciso por cierto que
nnlmridge_rbind = function (X, y, lambda, intercept = TRUE) {
if (intercept) {
lambdas = c(0, rep(lambda, ncol(X)))
X = cbind(1, X)
} else { lambdas = rep(lambda, ncol(X)) }
nnls(A=rbind(X,diag(sqrt(lambdas))), b=c(Y,rep(0,ncol(X))))$x
}
(y estrictamente hablando, solo la solución nnls(A=crossprod(X)+diag(lambdas), b=crossprod(X,Y))$x
es la correcta).
Todavía no he descubierto cómo el caso restringido de no negatividad podría optimizarse aún más para el p > n
caso; avíseme si alguien sabe cómo hacer esto ... [ lmridge_nnls_largep = function (X, Y, lambda) t(X) %*% nnls(A=tcrossprod(X)+lambda*diag(nrow(X)), b=Y)$x
no funciona]