Die Verallgemeinerung dieses Rezepts auf GLMs ist in der Tat nicht schwierig, da GLMs normalerweise unter Verwendung iterativ neu gewichteter kleinster Quadrate angepasst werden . Daher kann man innerhalb jeder Iteration den regulären gewichteten Schritt der kleinsten Quadrate durch einen Schritt der bestraften kleinsten Quadrate ersetzen, um einen bestraften Kamm-GLM zu erhalten. Tatsächlich wird dieses Rezept in Kombination mit adaptiven Ridge-Strafen verwendet, um mit L0 bestrafte GLMs (auch als beste Teilmenge bezeichnet, dh GLMs, bei denen die Gesamtzahl der Koeffizienten ungleich Null bestraft wird) anzupassen. Dies wurde zum Beispiel im l0ara-Paket implementiert , siehe dieses und dieses Dokument für Details.
Es ist auch erwähnenswert, dass die schnellste geschlossene Methode zur Lösung einer regulären Gratregression die Verwendung von ist
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]
}
für den Fall, wo n>=p
oder mit
lmridge_solve_largep = function (X, Y, lambda) (t(X) %*% solve(tcrossprod(X)+lambda*diag(nrow(X)), Y))[,1]
wann p>n
und für ein Modell ohne Intercept.
Dies ist schneller als die Verwendung des Rezepts für die Zeilenvergrößerung , dh das Ausführen
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))))
}
Wenn Sie für Ihre angepassten Koeffizienten Einschränkungen hinsichtlich der Nicht-Negativität benötigen , können Sie dies einfach tun
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
}
das ergibt dann übrigens ein etwas genaueres Ergebnis als
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
}
(und genau genommen nnls(A=crossprod(X)+diag(lambdas), b=crossprod(X,Y))$x
ist dann nur die Lösung die richtige).
Ich habe noch nicht herausgefunden, wie der Fall mit eingeschränkter Nicht-Negativität für den p > n
Fall weiter optimiert werden könnte - lassen Sie mich wissen, wenn jemand zufällig wissen würde, wie dies zu tun ist ... [ lmridge_nnls_largep = function (X, Y, lambda) t(X) %*% nnls(A=tcrossprod(X)+lambda*diag(nrow(X)), b=Y)$x
funktioniert nicht]