Реализация регрессии гребня: Выбор интеллектуальной сетки для ?

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, вы, вероятно, правы. Однако, если возможно, я хотел бы знать, есть ли какая-то сетка «по умолчанию». Например, я попытался получить сетку, выполнив , где и работал довольно хорошо для некоторых степеней свободы, но как , он взорвался. Это заставило меня задуматься о том, что, возможно, был какой-то изящный способ выбрать сетку для , о чем я и спрашиваю. Если этого не существует, я также был бы рад узнать (как я мог бы счастливо оставить метод Ньютона-Рапсона в своем коде, зная, что «лучшего способа не существует»). λ=log(s)λmax/log(smax)s=(1,2,...,smax)df(λ)pλ
Нестор
Чтобы лучше понять потенциальные трудности, с которыми вы сталкиваетесь, каковы типичные и наихудшие значения ? Есть ли что-то, что вы априори знаете о распределении собственных значений? p
кардинал
@cardinal, типичные значения в моем приложении будут варьироваться от до , но я хочу сделать это как можно более общим. Насчет распределения собственных значений не особо. - это матрица, которая содержит предикторы в своих столбцах, которые не всегда ортогональны. p1540X
Нестор
1
Ньютон-Рафсон , как правило , находит корни точность в пределах 3 до 4 шагов для р = 40 и малых значений DF (\ Lambda) ; почти никогда не более 6 шагов. Для больших значений иногда требуется до 30 шагов. Поскольку каждый шаг требует O (p) вычислений, общий объем вычислений несущественен. Действительно, число шагов, кажется, не зависит от p, если выбрано хорошее начальное значение (я выбираю тот, который вы использовали бы, если бы все d_i равнялись их среднему значению). 101234p=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 : Не будет общего алгебраического решения для нахождения корня . Это связано с тем, что существует эквивалентная задача поиска корней полинома степени и поэтому, если не очень мало (т. Е. Меньше пяти), никакого общего решения не будет. Итак, нам понадобится численный метод.dfλ
df(λ)y=0pp

Свойство 1 : функция выпуклая и убывает на . (Возьмем производные.) Следствие 1 (а) : алгоритм поиска корня Ньютона будет вести себя очень хорошо в этой ситуации. Пусть - требуемые степени свободы, а - соответствующий корень, т. . В частности, если мы начнем с любого начального значения (то есть, ), то последовательность итераций шага Ньютона будет монотонно сходиться к уникальное решениеdfλ0
yλ0y=df(λ0)λ1<λ0df(λ1)>yλ1,λ2,λ0 .
Следствие 1 (b) : Более того, если мы начнем с , то первый шаг приведет к , откуда он будет монотонно увеличиваться до решения по предыдущему следствию (см. Предостережение). ниже). Интуитивно, этот последний факт следует из того, что, если мы начнем справа от корня, производная слишком мала из-за выпуклости и поэтому первый шаг Ньютона приведет нас куда-то слева от корня. NB, поскольку не является вообще выпуклым для отрицательныхλ1>λ0λ2λ0dfdfλэто дает веские основания предпочитать начинать слева от нужного корня. В противном случае нам нужно дважды проверить, что шаг Ньютона не привел к отрицательному значению для предполагаемого корня, что может поместить нас где-то в невыпуклую часть . Следствие 1 (c) : Как только мы нашли корень для некоторого и затем ищем корень для некоторого , используя такой, что качестве нашего начального предположения гарантирует, что мы начинаем слева от второго корня. Таким образом, наша конвергенция гарантированно будет монотонной оттуда.df
y1y2<y1λ1df(λ1)=y1

Свойство 2 : Разумные границы существуют, чтобы дать «безопасные» отправные точки. Используя аргументы выпуклости и неравенство Дженсена, мы получаем следующие оценки Следствие 2. Это говорит нам о том, что корень удовлетворяющий подчиняется Итак, с точностью до общей константы мы корень между гармоническим и арифметическим средними .

p1+λpdi2df(λ)pidi2idi2+pλ.
λ0df(λ0)=y
()11pidi2(pyy)λ0(1pidi2)(pyy).
di2

Это предполагает, что для всех . Если это не так, то та же самая оценка имеет место, рассматривая только положительное и заменяя числом положительных . NB : Поскольку при условии, что все , то , поэтому границы всегда нетривиальны (например, нижняя граница всегда неотрицательна).di>0idipdidf(0)=pdi>0y(0,p]

Вот график «типичного» примера с . Мы наложили сетку размером 10 для степеней свободы. Это горизонтальные линии на графике. Вертикальные зеленые линии соответствуют нижней границе в .df(λ)p=400()

Example dof plot with grid and bounds

Алгоритм и пример кода R

Очень эффективный алгоритм, заданный сеткой желаемых степеней свободы в состоит в том, чтобы отсортировать их по убыванию, а затем последовательно найти корень каждого из них, используя предыдущий корень в качестве отправной точки для следующего 1. Мы можем уточнить это далее, проверив, больше ли каждый корень, чем нижняя граница для следующего корня, и, если нет, мы можем вместо этого начать следующую итерацию с нижней границы.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)))
}

Ниже приведен окончательный полный алгоритм, который принимает сетку точек и вектор ( не !).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. glmnet
  3. gcdnet

Выше приведены все пакеты R, так как вы используете Python, scikit-learn содержит реализации для риджа, лассо и эластичной сети.

sebp
источник
1
olsФункцию в R rmsпакете можно использовать численную оптимизацию , чтобы найти оптимальный штраф с использованием эффективной AIC. Но вы должны обеспечить максимальный штраф, который не всегда прост.
Фрэнк Харрелл
0

Возможная альтернатива в соответствии с источником ниже, кажется:

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

Если вы используете нормальное уравнение в качестве решателя или вычисляете дисперсию-ковариацию, вы уже должны были вычислить . Этот подход работает лучше всего, если вы оцениваете коэффициенты при различных значениях λ .(XX+λIp)1λ

Источник: https://onlinecourses.science.psu.edu/stat857/node/155

Хосе Баян Сантьяго Кальдерон
источник