Реалізація регресії хребта: вибір інтелектуальної сітки для


17

Я реалізую Ridge Regression в модулі Python / C, і я натрапив на цю "маленьку" проблему. Ідея полягає в тому, що я хочу взяти вибірку ефективних ступенів свободи в більшій чи меншій мірі однаковою мірою (як сюжет на стор. 65 у розділі "Елементи статистичного навчання" ), тобто зразок: де - власні значення матриці , від до \ mathrm {df} (\ lambda _ {\ min}) = p . Найпростіший спосіб встановити першу межу - дозволити \ lambda _ {\ max} = \ sum_i ^ p d_i ^ 2 / c (якщо вважати \ lambda _ {\ max} \ gg d_i ^ 2 ), де c

df(λ)=i=1pdi2di2+λ,
di2XTXdf(λmax)0df(λmin)=pλmax=ipdi2/cλmaxdi2cє невеликою постійною і представляє приблизно мінімальний ступінь свободи, який ви бажаєте взяти на вибірку (наприклад, c=0.1 ). Другий межа, звичайно, λmin=0 .

Як випливає з назви, тоді мені потрібно відібрати λ з λmin до λmax в деякій шкалі, щоб df(λ) була вибірковою (приблизно), скажімо, у 0.1 інтервали від c до p ... чи є простий спосіб це зробити? Я думав вирішити рівняння df(λ) для кожного λ за допомогою методу Ньютона-Рафсона, але це додасть занадто багато ітерацій, особливо коли p велике. Будь-які пропозиції?


1
Ця функція є спадною опуклою раціональною функцією λ0 . Коріння, особливо якщо вони вибрані через діадичну сітку, слід знайти дуже швидко.
кардинал

@cardinal, ти, мабуть, маєш рацію. Однак, якщо можливо, я хотів би знати, чи є якась сітка "за замовчуванням". Наприклад, я спробував отримати сітку, зробивши , де і працював досить добре для деяких ступенів свободи, але як , вона вибухнула. Це змусило мене замислитися, що, можливо, був якийсь акуратний спосіб вибрати сітку для , про що я прошу. Якщо цього не існує, я також був би радий знати (так як я міг щасливо залишити метод Ньютона-Рапсона у своєму коді, знаючи, що "кращого способу не існує"). з = ( 1 , 2 , . . . , секλ=log(s)λmax/log(smax)де(λ)Pλs=(1,2,...,smax)df(λ)pλ
Нестор

Для кращого уявлення про можливі труднощі, з якими ви стикаєтесь, які типові та найгірші значення ? Чи є щось, що ви знаєте апріорі про розподіл власних значень? p
кардинал

@cardinal, типові значення в моєму додатку становитимуть від до , але я хочу зробити це максимально загальним. Про розподіл власних значень не дуже. - це матриця, яка містить передбачувачі в стовпцях, які не завжди є ортогональними. 15 40 Хp1540X
Нестор

1
Ньютон-Рафсон зазвичай знаходить корені до точності протягом - кроків для та малих значень ; майже ніколи більше кроків. Для більших значень періодично потрібно до кроків. Оскільки кожен крок вимагає обчислень , загальна кількість обчислень є несуттєвою. Дійсно, кількість кроків, схоже, не залежить від якщо обрано хороше початкове значення (я вибираю той, який ви використали, якщо всі рівні їх середнього значення). 3 4 p = 40 d f ( λ ) 6 30 O ( p ) p d i101234p=40df(λ)630O(p)pdi
whuber

Відповіді:


19

Це довга відповідь . Отже, давайте тут наведемо короткочасну версію.

  • Немає приємного алгебраїчного вирішення цієї кореневої проблеми, тому нам потрібен числовий алгоритм.
  • Функція має безліч приємних властивостей. Ми можемо використати їх для створення спеціалізованої версії методу Ньютона для цієї проблеми із гарантованою монотонною конвергенцією до кожного кореня.df(λ)
  • Навіть мертвий Rкод, відсутній будь-які спроби оптимізації, може обчислити сітку розміром 100 з за кілька секунд. Ретельно написанийкод зменшив би це щонайменше на 2–3 порядки.p=100000C

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

Приклад : та рівномірна сітка для ступенів свободи розміру 100. Власні значення розподілені парето, отже, сильно перекошені. Нижче наведено таблиці кількості кроків Ньютона для пошуку кожного кореня.p=100000

# Table of Newton iterations per root.
# Without using lower-bound check.
  1  3  4  5  6 
  1 28 65  5  1 
# Table with lower-bound check.
  1  2  3 
  1 14 85 

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

Перш ніж надто глибоко копатись у речах, давайте збираємо деякі властивості та наслідки функції

df(λ)=i=1pdi2di2+λ.

Властивість 0 : - це раціональна функція λ . (Це видно з визначення.) Наслідок 0 : Не знайдеться загального алгебраїчного рішення для знаходження кореня d f ( λ ) - y = 0 . Це тому, що існує еквівалентна поліноміальна проблема кореневого пошуку ступеня p, і тому, якщо р не надзвичайно малий (тобто менше п’яти), загального рішення не буде. Отже, нам знадобиться числовий метод.dfλ
df(λ)y=0pp

Властивість 1 : Функція опукла і зменшується на λ 0 . (Візьміть похідні.) Наслідок 1 (а) : Алгоритм пошуку коренів Ньютона в цій ситуації буде вести себе дуже добре. Нехай y - бажані ступені свободи, а λ 0 - відповідний корінь, тобто y = d f ( λ 0 ) . Зокрема, якщо ми почнемо з будь-якого початкового значення λ 1 < λ 0 (значить, d f ( λ 1)dfλ0
yλ0y=df(λ0)λ1<λ0 ), то послідовність ітерацій кроків Ньютона λ 1 , λ 2 , монотоннобуде сходитисядо унікального рішення λ 0 . Наслідок 1 (b): Крім того, якби ми починали з λ 1 > λ 0 , топершийкрок дав би λ 2λ 0df(λ1)>yλ1,λ2,λ0
λ1>λ0λ2λ0, звідки він монотонно зросте до рішення попереднім наслідком (див. попередження нижче). Інтуїтивно цей останній факт випливає, тому що якщо ми почнемо праворуч від кореня, похідна буде "занадто" дрібною через опуклості і тому перший крок Ньютона перенесе нас кудись зліва від кореня. Примітка : Так як д е це НЕ в загальному опуклу для негативного Х , це дає серйозні підстави вважати за краще починаючи зліва від необхідного кореня. В іншому випадку нам потрібно ще раз перевірити, чи не призвів крок Ньютона до негативного значення для оціненого кореня, яке може розмістити нас десь у невипуклій частині d f . dfdfλdf
Наслідок 1 (с) : Після того, як ми знайшли корінь для деякого а потім шукаємо корінь з деякого y 2 < y 1 , використовуючи λ 1 такий, що d f ( λ 1 ) = y 1, як наша початкова здогадка гарантує, що ми починаємо зліва від другого кореня. Отже, наше зближення гарантовано буде монотонним звідти.y1y2<y1λ1df(λ1)=y1

Властивість 2 : Існують розумні межі, щоб дати "безпечні" вихідні точки. Використовуючи аргументи опуклості та нерівності Дженсена, ми маємо такі межі Наслідок 2: Це говорить нам, що корінь λ 0, що задовольняє d f ( λ 0 ) = y, підкоряється 1

p1+λpdi2df(λ)pidi2idi2+pλ.
λ0df(λ0)=y Отже, до загальної константи, ми засипали корінь між гармонічними та арифметичними засобамиd 2 i .
()11pidi2(pyy)λ0(1pidi2)(pyy).
di2

Це передбачає, що для всіх i . Якщо це не так, то ця ж межа дотримується, враховуючи лише додатне d i і замінюючи p на кількість позитивних d i . Примітка : Оскільки d f ( 0 ) = p, якщо вважати всі d i > 0 , то y ( 0 , p ] , причому межі завжди нетривіальні (наприклад, нижня межа завжди невід'ємна).di>0idipdidf(0)=pdi>0y(0,p]

Ось сюжет "типового" прикладу з р = 400 . Ми наклали сітку розміром 10 для ступенів свободи. Це горизонтальні лінії в сюжеті. Вертикальні зелені лінії відповідають нижній межі в ( ) .df(λ)p=400()

Example dof plot with grid and bounds

Алгоритм і деякий приклад R-коду

Дуже ефективний алгоритм, що дає сітку потрібних ступенів свободи in ( 0 , p ], - сортувати їх у порядку зменшення, а потім послідовно знаходити корінь кожного, використовуючи попередній корінь як вихідну точку для Ми можемо додатково уточнити це, перевіривши, чи кожен корінь перевищує нижню межу для наступного кореня, і, якщо ні, ми можемо почати наступну ітерацію на нижній межі.y1,yn(0,p]

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

# Newton's step for finding solutions to regularization dof.

dof <- function(lambda, d) { sum(1/(1+lambda / (d[d>0])^2)) }
dof.prime <- function(lambda, d) { -sum(1/(d[d>0]+lambda / d[d>0])^2) }

newton.step <- function(lambda, y, d)
{ lambda - (dof(lambda,d)-y)/dof.prime(lambda,d) }

# Full Newton step; Finds the root of y = dof(lambda, d).
newton <- function(y, d, lambda = NA, tol=1e-10, smart.start=T)
{
    if( is.na(lambda) || smart.start )
        lambda <- max(ifelse(is.na(lambda),0,lambda), (sum(d>0)/y-1)/mean(1/(d[d>0])^2))
    iter <- 0
    yn   <- Inf
    while( abs(y-yn) > tol )
    {
        lambda <- max(0, newton.step(lambda, y, d)) # max = pedantically safe
        yn <- dof(lambda,d)
        iter = iter + 1
    }
    return(list(lambda=lambda, dof=y, iter=iter, err=abs(y-yn)))
}

Нижче представлений остаточний повний алгоритм, який бере сітку точок і вектор ( не d 2 i !).di di2

newton.grid <- function(ygrid, d, lambda=NA, tol=1e-10, smart.start=TRUE)
{
    p <- sum(d>0)
    if( any(d < 0) || all(d==0) || any(ygrid > p) 
        || any(ygrid <= 0) || (!is.na(lambda) && lambda < 0) )
        stop("Don't try to fool me. That's not nice. Give me valid inputs, please.")
    ygrid <- sort(ygrid, decreasing=TRUE)
    out    <- data.frame()
    lambda <- NA
    for(y in ygrid)
    {
        out <- rbind(out, newton(y,d,lambda, smart.start=smart.start))
        lambda <- out$lambda[nrow(out)]
    }
    out
}

Зразок виклику функції

set.seed(17)
p <- 100000
d <- sqrt(sort(exp(rexp(p, 10)),decr=T))
ygrid <- p*(1:100)/100
# Should take ten seconds or so.
out <- newton.grid(ygrid,d)

Улюблене питання, щоб я міг повернутися до цієї відповіді. Дякую, що опублікував цей детальний аналіз, кардинал.
Макрос

Дивовижна відповідь :-), дякую великому кардиналу за пропозиції та відповідь.
Нестор

1

Крім того, існує пара методів, які дозволять ефективно обчислити повний шлях регуляризації:

  1. GPS
  2. глмнет
  3. gcdnet

Наведені вище всі R-пакети, оскільки ви використовуєте Python, scikit-learn містить реалізацію для хребта, ласо та еластичної мережі.


1
olsФункцію в R rmsпакеті можна використовувати чисельну оптимізацію , щоб знайти оптимальний штраф з використанням ефективної AIC. Але ви повинні забезпечити максимальний штраф, який не завжди є простим.
Френк Харрелл

0

Можливою альтернативою згідно з джерелом, поданим нижче, здається, є:

Рішення закритої форми: df(λ)=tr(X(XX+λIp)1X)

Should you be using the normal equation as the solver or computing the variance-covariance estimate, you should already have computed (XX+λIp)1. This approach works best if you are estimating the coefficients at the various λ.

Source: https://onlinecourses.science.psu.edu/stat857/node/155

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