In effetti, generalizzare questa ricetta con i GLM non è difficile in quanto i GLM sono generalmente adatti usando i minimi quadrati iterativamente ripesati . Quindi, all'interno di ogni iterazione si può sostituire il gradino dei minimi quadrati ponderati regolari con un gradino dei minimi quadrati ponderati con cresta penalizzata per ottenere un GLM penalizzato con cresta. In effetti, in combinazione con penalità adattive della cresta, questa ricetta viene utilizzata per adattarsi a GLM penalizzati L0 (ovvero il miglior sottoinsieme, ovvero GLM in cui viene penalizzato il numero totale di coefficienti diversi da zero). Questo è stato implementato ad esempio nel pacchetto l0ara , vedere questo documento e questo per i dettagli.
Vale anche la pena notare che sta usando il modo più veloce in forma chiusa per risolvere una regressione della cresta regolare
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]
}
nel caso in cui n>=p
o utilizzando
lmridge_solve_largep = function (X, Y, lambda) (t(X) %*% solve(tcrossprod(X)+lambda*diag(nrow(X)), Y))[,1]
quando p>n
e per un modello senza intercettazione.
Questo è più veloce rispetto all'utilizzo della ricetta per l'aumento di riga , ovvero fare
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))))
}
Se ti capita di aver bisogno di vincoli di non negatività sui tuoi coefficienti adattati, allora puoi semplicemente farlo
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
}
che quindi dà un risultato leggermente più accurato tra
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
}
(e a rigor di termini solo la soluzione nnls(A=crossprod(X)+diag(lambdas), b=crossprod(X,Y))$x
è quindi quella corretta).
Non ho ancora capito come il caso vincolato dalla non negatività potrebbe essere ulteriormente ottimizzato per il p > n
caso - fammi sapere se qualcuno capita come fare per farlo ... [ lmridge_nnls_largep = function (X, Y, lambda) t(X) %*% nnls(A=tcrossprod(X)+lambda*diag(nrow(X)), b=Y)$x
non funziona]