Оновлення ласо підходило до нових спостережень


12

Я підганяю L1-регульовану лінійну регресію до дуже великого набору даних (з n >> p.) Змінні відомі заздалегідь, але спостереження надходять невеликими шматками. Я хотів би підтримувати придатність ласо після кожного шматка.

Я, очевидно, можу перевстановити всю модель, побачивши кожен новий набір спостережень. Однак це було б досить неефективно, враховуючи, що є багато даних. Кількість нових даних, що надходить на кожен крок, дуже мала, і придатність навряд чи сильно зміниться між кроками.

Чи можна щось зробити, щоб зменшити загальне обчислювальне навантаження?

Я дивився на алгоритм LARS Efron та ін., Але був би радий розглянути будь-який інший метод підгонки, якщо його можна зробити для «теплого старту» так, як описано вище.

Примітки:

  1. Я в основному шукаю алгоритм, але вказівки на існуючі програмні пакети, які можуть це зробити, також можуть виявити проникливий.
  2. На додаток до поточних траєкторій ласо, алгоритм, звичайно, вітається для збереження іншого стану.

Бредлі Ефрон, Тревор Хасті, Ієн Джонстоун та Роберт Тібшірані, регресія в найменшому куті , анали статистики (з обговоренням) (2004) 32 (2), 407--499.

Відповіді:


7

Ласо встановлюється через LARS (ітераційний процес, який починається з деякої початкової оцінки ). За замовчуванням але ви можете змінити це в більшості реалізації (і замінити його на оптимальний вас уже є). Чим ближче до , тим менша кількість ітерацій LARS, які вам доведеться перейти, щоб дістатися до .β 0 = 0 p β o l d β o l d β n e w β n e wβ0β0=0pβoldβoldβnewβnew

Редагувати:

Завдяки коментарям від 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, в Rdo (я припускаю, 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 ) )

Моя думка, якщо у вас є нові дані, вам просто потрібно

  1. оновити ( не замінити) матрицю обмеження та вектор функції функції для врахування нових спостережень.
  2. змінити початкові точки внутрішньої точки від

    x0 = c (rep (0, m), rep (1, m))

    до вектору розчину, який ви знайшли раніше (до того, як нові дані були додані). Логіка тут така. Позначимо новий вектор коефіцієнтів (ті, що відповідають набору даних після оновлення) та вихідні. Також вектор у наведеному вище коді (це звичайний початок для методу внутрішньої точки). Тоді ідея полягає в тому, що якщо: β o l d β i n i tβnewβoldβinitx0

|βinitβnew|1>|βnewβold|1(1)

тоді можна отримати набагато швидше, запустивши внутрішню точку з а не з наївного . Коефіцієнт посилення буде тим більш важливим, коли розміри набору даних ( і ) будуть більшими. β o l d β i n i t n pβnewβoldβinitnp

Що стосується умов, за яких виконується нерівність (1), то вони:

  • коли велика порівняно з (це зазвичай буває, коли , кількість змінних конструкції велика порівняно з , кількість спостережень)| β O L S | 1 р нλ|βOLS|1pn
  • коли нові спостереження не мають патологічного впливу, наприклад, коли вони узгоджуються зі стохастичним процесом, що створив існуючі дані.
  • коли розмір оновлення невеликий відносно розміру існуючих даних.

Дякую, але я боюся, що не дотримуюся. LARS створює кусково-лінійний шлях (з рівно балами за найменші кути і, можливо, більше точок для ласо.) Кожна точка має свій набір . Коли ми додамо більше спостережень, всі бета-версії можуть переміщуватися (крім , це завжди .) Чи можете ви розширити свою відповідь? Дякую. β β 0 0 pp+1ββ00p
NPE

@aix: Ви хочете оновити весь шлях до ласо або просто рішення? (тобто зафіксовано обмежене покарання?).
user603

λ
β^lasso=argminβ{12i=1N(yiβ0j=1pxijβj)2+λj=1p|βj|}

β

1
Будь-які бібліотеки, які ви знаєте, можуть це зробити, не редагуючи вихідний код?
користувач2763361
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.