Le lasso est ajusté par LARS (un processus itératif, qui commence à une estimation initiale ). Par défaut β 0 = 0 p mais vous pouvez changer cela dans la plupart des implémentations (et le remplacer par le β ∗ o l d optimal que vous avez déjà). Plus β ∗ o l d est proche de β ∗ n e w , plus le nombre d'itérations LARS que vous devrez franchir pour arriver à β ∗ n e w est petit .β0β0= 0pβ∗o l dβ∗o l dβ∗n e wβ∗n e w
ÉDITER:
En raison des commentaires de, user2763361
j'ajoute plus de détails à ma réponse d'origine.
D'après les commentaires ci-dessous, je suppose que user2763361 suggère de compléter ma réponse originale pour la transformer en une qui peut être utilisée directement (hors des étagères) tout en étant très efficace.
Pour faire la première partie, je vais illustrer la solution que je propose pas à pas sur un exemple de jouet. Pour satisfaire la deuxième partie, je le ferai en utilisant un solveur de point intérieur récent et de haute qualité. En effet, il est plus facile d'obtenir une implémentation haute performance de la solution que je propose en utilisant une bibliothèque qui peut résoudre le problème du lasso par l'approche du point intérieur plutôt que d'essayer de pirater l'algorithme LARS ou simplex pour démarrer l'optimisation à partir d'un non point de départ standard (bien que ce deuxième lieu soit également possible).
Notez qu'il est parfois affirmé (dans des livres plus anciens) que l'approche du point intérieur pour résoudre des programmes linéaires est plus lente que l'approche simplex et cela peut être vrai il y a longtemps, mais ce n'est généralement pas vrai aujourd'hui et certainement pas vrai pour les problèmes à grande échelle (c'est pourquoi la plupart des bibliothèques professionnelles aiment cplex
utiliser l'algorithme de point intérieur) et la question concerne au moins implicitement les problèmes à grande échelle. Notez également que le solveur de point intérieur que j'utilise gère entièrement les matrices clairsemées, donc je ne pense pas qu'il y aura un grand écart de performances avec LARS (une motivation originale pour utiliser LARS était que de nombreux solveurs LP populaires à l'époque ne manipulaient pas bien les matrices clairsemées et ce sont des caractéristiques du problème LASSO).
Une (très) bonne implémentation open source de l'algorithme de point intérieur se trouve ipopt
dans la COIN-OR
bibliothèque. Une autre raison pour laquelle je vais utiliser ipopt
est qu'il a doté d' une interface R, ipoptr
. Vous trouverez un guide d'installation plus complet ici , ci-dessous je donne les commandes standard pour l'installer ubuntu
.
dans le bash
, faites:
sudo apt-get install gcc g++ gfortran subversion patch wget
svn co https://projects.coin-or.org/svn/Ipopt/stable/3.11 CoinIpopt
cd ~/CoinIpopt
./configure
make
make install
Ensuite, en tant que root, dans R
do (je suppose qu'il svn
a copié le fichier de subversion ~/
comme il le fait par défaut):
install.packages("~/CoinIpopt/Ipopt/contrib/RInterface",repos=NULL,type="source")
De là, je donne un petit exemple (principalement de l'exemple de jouet donné par Jelmer Ypma dans le cadre de son R
emballage ipopt
):
library('ipoptr')
# Experiment parameters.
lambda <- 1 # Level of L1 regularization.
n <- 100 # Number of training examples.
e <- 1 # Std. dev. in noise of outputs.
beta <- c( 0, 0, 2, -4, 0, 0, -1, 3 ) # "True" regression coefficients.
# Set the random number generator seed.
ranseed <- 7
set.seed( ranseed )
# CREATE DATA SET.
# Generate the input vectors from the standard normal, and generate the
# responses from the regression with some additional noise. The variable
# "beta" is the set of true regression coefficients.
m <- length(beta) # Number of features.
A <- matrix( rnorm(n*m), nrow=n, ncol=m ) # The n x m matrix of examples.
noise <- rnorm(n, sd=e) # Noise in outputs.
y <- A %*% beta + noise # The outputs.
# DEFINE LASSO FUNCTIONS
# m, lambda, y, A are all defined in the ipoptr_environment
eval_f <- function(x) {
# separate x in two parts
w <- x[ 1:m ] # parameters
u <- x[ (m+1):(2*m) ]
return( sum( (y - A %*% w)^2 )/2 + lambda*sum(u) )
}
# ------------------------------------------------------------------
eval_grad_f <- function(x) {
w <- x[ 1:m ]
return( c( -t(A) %*% (y - A %*% w),
rep(lambda,m) ) )
}
# ------------------------------------------------------------------
eval_g <- function(x) {
# separate x in two parts
w <- x[ 1:m ] # parameters
u <- x[ (m+1):(2*m) ]
return( c( w + u, u - w ) )
}
eval_jac_g <- function(x) {
# return a vector of 1 and minus 1, since those are the values of the non-zero elements
return( c( rep( 1, 2*m ), rep( c(-1,1), m ) ) )
}
# ------------------------------------------------------------------
# rename lambda so it doesn't cause confusion with lambda in auxdata
eval_h <- function( x, obj_factor, hessian_lambda ) {
H <- t(A) %*% A
H <- unlist( lapply( 1:m, function(i) { H[i,1:i] } ) )
return( obj_factor * H )
}
eval_h_structure <- c( lapply( 1:m, function(x) { return( c(1:x) ) } ),
lapply( 1:m, function(x) { return( c() ) } ) )
# The starting point.
x0 = c( rep(0, m),
rep(1, m) )
# The constraint functions are bounded from below by zero.
constraint_lb = rep( 0, 2*m )
constraint_ub = rep( Inf, 2*m )
ipoptr_opts <- list( "jac_d_constant" = 'yes',
"hessian_constant" = 'yes',
"mu_strategy" = 'adaptive',
"max_iter" = 100,
"tol" = 1e-8 )
# Set up the auxiliary data.
auxdata <- new.env()
auxdata$m <- m
auxdata$A <- A
auxdata$y <- y
auxdata$lambda <- lambda
# COMPUTE SOLUTION WITH IPOPT.
# Compute the L1-regularized maximum likelihood estimator.
print( ipoptr( x0=x0,
eval_f=eval_f,
eval_grad_f=eval_grad_f,
eval_g=eval_g,
eval_jac_g=eval_jac_g,
eval_jac_g_structure=eval_jac_g_structure,
constraint_lb=constraint_lb,
constraint_ub=constraint_ub,
eval_h=eval_h,
eval_h_structure=eval_h_structure,
opts=ipoptr_opts,
ipoptr_environment=auxdata ) )
Mon point est, si vous avez de nouvelles données, vous avez juste besoin de
- mettre à jour (et non remplacer) la matrice de contraintes et le vecteur de fonction objectif pour tenir compte des nouvelles observations.
changer les points de départ du point intérieur de
x0 = c (rep (0, m), rep (1, m))
βn e wβo l dβi n i tx0
| βi n i t- βn e w|1> | βn e w- βo l d|1( 1 )
βn e wβo l dβi n i tnp
Quant aux conditions de détention de l'inégalité (1), elles sont:
- λ| βO L S|1pn
- lorsque les nouvelles observations n'ont pas d'influence pathologique, par exemple lorsqu'elles sont cohérentes avec le processus stochastique qui a généré les données existantes.
- lorsque la taille de la mise à jour est petite par rapport à la taille des données existantes.