Ласо встановлюється через LARS (ітераційний процес, який починається з деякої початкової оцінки ). За замовчуванням але ви можете змінити це в більшості реалізації (і замінити його на оптимальний вас уже є). Чим ближче до , тим менша кількість ітерацій LARS, які вам доведеться перейти, щоб дістатися до .β 0 = 0 p β ∗ o l d β ∗ o l d β ∗ n e w β ∗ n e wβ0β0= 0pβ∗o l dβ∗o l dβ∗н е шβ∗н е ш
Редагувати:
Завдяки коментарям від user2763361
моєї оригінальної відповіді я додаю більше деталей.
З наведених нижче коментарів я розумію, що користувач2763361 пропонує доповнити мою оригінальну відповідь, щоб перетворити її на ту, яку можна використовувати безпосередньо (з полиць), а також бути дуже ефективною.
Щоб виконати першу частину, я проілюструю рішення, яке пропоную покроково на прикладі іграшки. Щоб задовольнити другу частину, я зроблю це, використовуючи недавній високоякісний вирішувач інтер'єру. Це тому, що простіше отримати високу продуктивність реалізації рішення, я пропоную використовувати бібліотеку, яка може вирішити проблему lasso за допомогою внутрішнього підходу, а не намагатися зламати алгоритм LARS або симплекс, щоб почати оптимізацію з не- стандартна відправна точка (хоча це також можливе друге місце).
Зауважте, що іноді стверджується (у старих книгах), що підхід до вирішення лінійних програм у внутрішній точці відбувається повільніше, ніж симплексний підхід, і це, можливо, було давно, але сьогодні це, як правило, не вірно і, звичайно, не відповідає великим проблемам масштабу (саме тому більшість професійних бібліотек люблять cplex
використовувати алгоритм точок інтер’єру), і питання принаймні неявно стосується великих масштабних проблем. Зауважте також, що вирішувач точок в інтер'єрі, який я використовую, повністю обробляє рідкісні матриці, тому я не думаю, що з LARS буде великий розрив у продуктивності (оригінальна мотивація використання LARS полягала в тому, що багато популярних вирішувачів LP в той час не обробляли рідкісні матриці і це характерні особливості проблеми LASSO).
(Дуже) хороша реалізація алгоритму точок інтер'єру з відкритим кодом є ipopt
в COIN-OR
бібліотеці. Ще одна причина , яку я буду використовувати в ipopt
тому , що вона має має інтерфейс R, ipoptr
. Ви знайдете більш вичерпний посібник з установки тут , нижче я даю стандартні команди для його встановлення ubuntu
.
в bash
, зробіть:
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
Потім, як root, в R
do (я припускаю, svn
що скопіював файл subversion, ~/
як це робиться за замовчуванням):
install.packages("~/CoinIpopt/Ipopt/contrib/RInterface",repos=NULL,type="source")
Звідси я наводжу невеликий приклад (здебільшого із прикладу іграшки, який Елмер Йпма дав у складі своєї R
обгортки 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 ) )
Моя думка, якщо у вас є нові дані, вам просто потрібно
- оновити ( не замінити) матрицю обмеження та вектор функції функції для врахування нових спостережень.
змінити початкові точки внутрішньої точки від
x0 = c (rep (0, m), rep (1, m))
до вектору розчину, який ви знайшли раніше (до того, як нові дані були додані). Логіка тут така. Позначимо новий вектор коефіцієнтів (ті, що відповідають набору даних після оновлення) та вихідні. Також вектор у наведеному вище коді (це звичайний початок для методу внутрішньої точки). Тоді ідея полягає в тому, що якщо: β o l d β i n i tβн е шβo l dβi n i tx0
| βi n i t- βн е ш|1> | βн е ш- βo l d|1( 1 )
тоді можна отримати набагато швидше, запустивши внутрішню точку з
а не з наївного . Коефіцієнт посилення буде тим більш важливим, коли розміри набору даних ( і ) будуть більшими. β o l d β i n i t n pβн е шβo l dβi n i tнp
Що стосується умов, за яких виконується нерівність (1), то вони:
- коли велика порівняно з (це зазвичай буває, коли , кількість змінних конструкції велика порівняно з , кількість спостережень)| β O L S | 1 р нλ|βO L S|1pн
- коли нові спостереження не мають патологічного впливу, наприклад, коли вони узгоджуються зі стохастичним процесом, що створив існуючі дані.
- коли розмір оновлення невеликий відносно розміру існуючих даних.