Це довга відповідь . Отже, давайте тут наведемо короткочасну версію.
- Немає приємного алгебраїчного вирішення цієї кореневої проблеми, тому нам потрібен числовий алгоритм.
- Функція має безліч приємних властивостей. Ми можемо використати їх для створення спеціалізованої версії методу Ньютона для цієї проблеми із гарантованою монотонною конвергенцією до кожного кореня.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=1pd2id2i+λ.
Властивість 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+λp∑d−2i≤df(λ)≤p∑id2i∑id2i+pλ.
λ0df(λ0)=y
Отже, до загальної константи, ми засипали корінь між гармонічними та арифметичними засобами
d 2 i .
11p∑id−2i(p−yy)≤λ0≤(1p∑id2i)(p−yy).(⋆)
d2i
Це передбачає, що для всіх 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(⋆)
Алгоритм і деякий приклад 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 d2i
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)