L1 и L2-регуляризация для логистической регрессии

В этой лекции мы рассмотрим отличия между L1 и L2-регуляризацией в логистической регрессии и покажем, как эти отличия появляются вследствие математических выкладок. Мы также рассмотрим теорию и код для  L1 и L2-регуляризации. Мы начнем сразу с различий, а затем объясним, вследствие чего они возникают.

Мы уже видели, что L1-регуляризация способствует разреженности функции, когда лишь немногие факторы не равны нулю. L2-регуляризация способствует появлению малых весовых коэффициентов модели, но не способствует их точному равенству нулю. В этой лекции мы обсудим, почему так получается.

Обратите внимание, что оба метода помогают улучшить обобщение и ошибки теста, поскольку не допускают переобучения модели из-за шума в данных.

L1-регуляризация реализует это путём отбора наиболее важных факторов, которые сильнее всего влияют на результат. Для простоты можете считать, что факторы с малой величиной влияния на конечный результат фактически «помогают» вам предсказывать лишь шум в наборе обучающих данных. L2-регуляризация предотвращает переобучения модели путём запрета на непропорционально большие весовые коэффициенты.

Для начала пройдёмся по уже существующим и использующимся методикам. Их стоит изучить, поскольку я считаю, что они неадекватны и отвлекают много ресурсов. 

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

Что на самом деле полезно – представить себе модель с одномерным весовым коэффициентом.

При L2-регуляризации дополнительный член является квадратичной функцией, при L1-регуляризации – модулем. Что здесь действительно важно – производная функции. Производная, конечно, является ключевой, поскольку градиентный спуск в основном движется в направлении производной.

При квадратичном члене, чем ближе вы находитесь к нулю, тем меньшей становится ваша производная, пока также не приблизится к нулю. Поэтому при L2-регуляризации, когда ваша величина w уже мала, дальнейший градиентный спуск уже её сильно не изменит. В случае модуля производная является константой с абсолютной величиной, равной единице. Формально в нуле она не определена, но мы считаем её также равной нулю. Поэтому при L1-регуляризации градиентный спуск будет стремиться к нулю с постоянной скоростью, а достигнув его, там и останется. Вследствие этого L2-регуляризация способствует малой величине весовых коэффициентов, а L1-регуляризация способствует их равенству нулю, тем самым провоцируя разрежённость.

И наконец, обратите внимание, что вы можете включить в свою модель сразу и L1, и L2-регуляризации. Такая модель даже имеет специальное название – ElasticNet. Звучит, конечно, довольно причудливо, но на самом деле это просто добавление и штрафа L1-регуляризации, и штрафа L2-регуляризации к вашей функции затрат.

JRIDGE = J + λ2|w|2,

JLASSO = J +λ1|w|,

JELASTICNET = J + λ1|w| + λ2|w|2.

L1-регуляризация. Теория

На предыдущих лекциях мы говорили об обобщении и переобучении. Мы видели, что даже когда мы добавляем столбец случайного шума к нашим данным, мы всё же можем улучшить наш показатель обучения. В общем случае мы хотим, чтобы размерность нашего X была намного меньше количества наблюдений N. Другая возможная проблема заключается в том, что при определённых наборах данных размерность намного больше, чем количество наблюдений.

Один из способов показать это наглядно – построить матрицу X. Мы хотим, чтобы наша матрица X была тонкой, когда N велико, а D – мало. В обратном же случае, когда матрица X широка, N мало, а D велико, и получается не очень хорошо, а нам нужно предпринять некоторые действия, чтобы избежать потенциальных проблем.

В такой ситуации мы можем из всего массива факторов отобрать лишь небольшое количество важнейших, задающих тенденцию и удалить все остальные, являющиеся просто шумом. Это называется разрежением, поскольку большинство факторов будет равно нулю, и лишь небольшое их число не будет равным нулю. В этой лекции мы обсудим L1-регуляризацию, позволяющую нам достичь разрежения.

В основе L1-регуляризации лежит достаточно простая идея. Как и в случае L2-регуляризации, мы просто добавляем штраф к первоначальной функции затрат. Подобно тому, как в L2-регуляризации мы используем L2-нормирование для поправки весовых коэффициентов, в L1-регуляризации мы используем специальное L1-нормирование. L2-регуляризация называется также регрессией Риджа, а L1-регуляризация – лассо-регрессией.

J_{RIDGE} = - \sum_{i=1}^{N} (t_n log\; y_n + (1 - t_n) \;log (1 - y_n))+ \lambda \parallel w\parallel^2_2,

J_{LASSO} = - \sum_{i=1}^{N} (t_n log\; y_n + (1 - t_n) \;log (1 - y_n))+ \lambda \parallel w\parallel_1.

Прежде чем мы займёмся решением задачи, давайте рассмотрим распределение вероятности. Вы знаете, что экспонента отрицательного квадрата – это распределение Гаусса, поэтому при L2-регуляризации мы имели гауссово правдоподобие и гауссов приор для w. В данном же случае у нас больше нет гауссова приора по w.

Какое распределение имеет отрицательное абсолютное значение в экспоненте? Это распределение Лапласа.

p (w) = \frac {\lambda} {2} exp (- \lambda |w|).

Таким образом, при L1-регуляризации мы имеем лапласовый распределённый приор весовых коэффициентов и находим решение для апостериора относительно w c лапласовым приором.

В случае логистической регрессии вы уже знаете, как решать эту задачу. Мы находим градиент и двигаемся в его направлении:

J = - \sum_{n=1}^{N} (t_n \;log\;y_n + (1 - t_n)\; log (1 - y_n)) +\lambda ||w||,

\frac {\partial J} {\partial w} = X^T (Y - T) + \lambda sign (w).

При L1-регуляризации вы уже знаете, как находить градиент первой части уравнения. Вторая же часть представляет собой λ, умноженную на функцию sign(x). Функция sign(x) возвращает единицу, если x>0,  минус единицу, если x<0, и нуль, если x=0.

L1-регуляризация. Код

Предлагаю совместно написать код, демонстрирующий использование L1-регуляризации.

План состоит в том, что мы сгенерируем некоторые данные, где входные переменные представлены широкой матрицей, тогда как Y будет зависеть лишь от нескольких факторов, а остальные будут лишь шумом. Затем мы используем L1-регуляризацию, чтобы найти разрежённые весовые коэффициенты, определяющие полезные размерности X.

Если вы не хотите сами писать код, а лишь запустить его, то соответствующий файл находится в репозитарии под названием l1_regularization.py.

Итак, начнём с импорта библиотек Numpy и Matplotlib.

import numpy as np

import matplotlib.pyplot as plt

Определим также нашу сигмоидную функцию. Вы уже с ней знакомы.

def sigmoid(z):

return 1 / (1 + np.exp(-z))

Установим N=50 и D=50, чтобы это была широкая матрица. Значения X установим равномерно распределёнными в диапазоне от -5 до +5.

N = 50

D = 50

X = (np.random.random((N,D)) – 0.5)*10

Истинные значения весовых коэффициентов, определяемые переменной true_w, уставим равными 1, 0,5 и -0,5, так что только первые три размерности имеют значение, остальные же 47 размерностей поставим равными нулю, никак не влияющими на результат.

true_w = np.array([1, 0.5, -0.5] + [0]*(D-3))

Теперь определим наше Y. Это будет сигмоида от X плюс некоторый случайный шум.

Y = np.round(sigmoid(X.dot(true_w) + np.random.randn(N)*0.5))

Следующее – градиентный спуск.

Коэффициент обучения установим равным 0,001, штраф при L1-нормализации установим равным 2. Я рекомендую вам поэкспериментировать с различными значениями штрафа и посмотреть, что получится. Количество итераций установим равным 5000. Кроме того, рассчитаем значение функции затрат. Мы уже знаем, как это делать.

costs[]

w = np.random.randn(D) / np.sqrt(D)

learning_rate = 0.001

l1 = 2.0

for t in xrange(5000):

Yhat = sigmoid(X.dot(w))

delta = Yhat – Y

w = w – learning_rate*(X.T.dot(delta) + l1*np.sign(w))

cost = -(Y*np.log(Yhat) + (1-Y)*np.log(1 – Yhat)). mean() + l1*np.abs(w).mean()

costs.append(cost)

plt.plot(costs)

plt.show()

И наконец, построим графики истинных весовых коэффициентов с вычисленными весовыми коэффициентами.

plt.plot(true_w, label=’true w’)

plt.plot(w, label=’w map’)

plt.legend()

plt.show()

Запустим программу и посмотрим, что получилось.

Как мы видим, функция затрат сходится довольно быстро. Значение весовых коэффициентов вычислено неплохо, но оно не совсем совпадает с настоящими.

Попробуем ещё раз, но поставим штраф L1-регуляризации равным 10.

l1 = 10.0

Видим новую функцию затрат и весовые коэффициенты.

Коэффициенты теперь намного ближе к нулю, поскольку сдвинуты в эту область регуляризацией. Поэтому пробуйте выставлять меньший штраф регуляризации, чтобы достичь успеха. Если получается хорошо, то сохраните его значение как можно более близким к нулю.

L2-регуляризация. Теория

Обсудим популярнейшую тему машинного обучения – регуляризацию. Мы рассмотрим её  с нескольких точек зрения, чтобы вы полностью понимали причины использования регуляризации и её теоретические последствия.

Прежде всего рассмотрим проблему переобученности. Вернёмся к нашим гауссовым облакам, одно из которых концентрируется к точке с координатами (2; 2), а второй – к точке с координатами (-2; -2). Это ровно та самая задача, для которой мы нашли решение байесовского классификатора. Её легко изобразить графически – как правило, это два круга, разделённые прямой. Как вы знаете, найденное нами решение байесовского классификатора есть w = [0, 4, 4], где 0 – это смещение.

Какая линия соответствует этому решению? Как мы знаем из курса математики, уравнение прямой имеет вид

Обратите внимание, что в этом уравнении y представляет собой ординату на координатой плоскости, а не исходящий результат логистической регрессии. Мы можем переписать наше уравнение в виде

Следовательно, угловой коэффициент прямой равен -1, а свободный член, характеризующий пересечение с осью y, равен нулю.

Это может заставить вас задуматься – а почему решение для байесовского классификатора равно (4, 4)? Почему не (1, 1) или не (10, 10)? Действительно, ведь все эти решения характеризуют одну и ту же прямую! В этом и заключается первая подсказка, зачем нам может понадобиться регуляризация.

Рассмотрим целевую функцию:

J = - [t * \;log (y) + (1 - t)\; * log (1 - y)],

Отметим, что y здесь означает именно исходящий результат логистической регрессии.

Возьмём некоторую точку (x1; x2) с координатами (1; 1). Мы знаем, что она принадлежит к тому же множеству точек, которые концентрируются в районе точки с координатами (2; 2), то есть принадлежит классу 1. Если мы подставим значение нашей точки в формулу логистической регрессии с данными значениями весовых коэффициентов w = [0, 4, 4], то получим значение сигмоиды

σ(0 + 4 + 4) = σ(8) = 0,99966.

Лучшим, чем этот, может быть только результат, равный единице. Таким образом, при y = σ(8) целевая функция равна примерно -0,0003.

А что будет, если весовые коэффициенты будут равны (0, 1, 1)? В таком случае целевая функция будет иметь значение примерно -0,12 – а это уже не такой хороший показатель. Если же установить весовые коэффициенты равными (0, 10, 10), то значение целевой функции будет приблизительно равно -2,0*10-9.

Мораль же всей истории в том, что лучшими весовыми коэффициентами для модели будут (0, бесконечность, бесконечность). Конечно же, компьютер не может обрабатывать такие числа и выдаст ошибку.

Далее, люди часто понимают регуляризацию в понятиях регрессии из моего предыдущего курса линейной регрессии. Но сейчас мы рассматриваем не регрессию, поэтому такое представление неприменимо. В действительности даже если наши данные занимают весь диапазон возможных значений входных переменных, никакой переобученности не возникает, даже если наша модель очень сложна. Именно по этой причине всегда желательно иметь как можно больше данных. Переобученность возникает тогда, когда модель пытается «угадать» результат в области, где до этого не было никаких данных. Если же ваш учебный набор распространяется на весь объём данных и включает в себя все возможные значения, то у вас есть возможность хорошо обучить модель. Иными словами, если ваш учебный набор данных выглядит точно так же, как и проверочный, и модель показывает хороший результат на учебном наборе данных, то она покажет такой же хороший результат и на проверочном.

В отличие от предыдущего случая, сейчас даже если наши данные хорошо сбалансированы и включают в себя все возможные варианты входящих переменных, логистическая регрессия всё равно пытается дать решение, которое компьютер не может вычислить.

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

J = - [t * \;log (y) + (1 - t)\; * log (1 - y)],

то в формулу можно добавить дополнительный член, который будет увеличивать значение функции ошибки, если весовые коэффициенты чересчур велики:

J_{reg}= J + (\frac {\lambda} {2}) || w||^2 = J + (\frac {\lambda} {2}) w^T w.

Это вынуждает весовые коэффициенты стремиться к нулю, и теперь не получатся весовые коэффициенты вроде (0, 10, 10), поскольку в таком случае значение функции ошибок будет очень велико.

Член λ называется параметром сглаживания. Он балансирует кросс-энтропийную функцию ошибок и регуляризационный штраф. Если значение λ велико, весовые коэффициенты будут стремиться к нулю, если же значение λ мало или равно нулю, то весовые коэффициенты будут просто стремиться к минимизации кросс-энтропийной функции ошибок. Как правило, значение параметра λ устанавливают 0,1 или 1, или в районе между этими значениями, но в основном его значение зависит от конкретных данных. Вам нужно попробовать разные значения и понаблюдать за поведением функции затрат и конечным результатом. Не существует универсальной методики определения значения параметра λ. Вернее, она, может, и существует, но это чересчур сложно для наших занятий.

Итак, как это влияет на нахождение весовых коэффициентов?

Не забывайте, что при градиентном спуске всё, что нам нужно сделать, – это найти градиент целевой функции и двигаться в его направлении. Поскольку добавление нового члена не влияет на вычисление градиентного спуска, все градиенты можно находить по отдельности.

Рассмотрим подробнее градиент со штрафами регуляризации. С одной стороны, его можно рассматривать в скалярной форме. В таком случае штраф равен:

reg\;cost = (\frac {\lambda} {2}) (w^2_0 + w^2_1 + w^2_2 +\;...

В этом случае производная для любого заданного wi будет равна:

\frac {d(reg\;cost)} {dw_i} = \lambda w_i.

В векторной форме новый градиент будет равен:

\frac {dJ_{reg}} {dw} = X^T (Y - T) + \lambda w.

Рассмотрим теперь другую интерпретацию регуляризации. Как вы помните, мы объясняем нашу модель ещё и в понятиях теории вероятностей, и нахождение минимума кросс-энтропийной функции ошибок является также нахождением максимума функции правдоподобия. Вернёмся к нашей целевой функции как такой, чей максимум мы хотим найти. Тогда

J = + [t * log\; y + (1 - t) * log (1 - y)] - (\lambda/2) \;* \;\parallel w\parallel^2.

Возьмём теперь экспоненту:

expJ = y^t (1 - y)^{(1 - t)} * exp (\frac {- \lambda \parallel w\parallel^2} {2}).

Экпоненциированная первая часть – это биноминальное распределение для функции правдоподобия. Второй же экспоненциированный квадратичный член со знаком «минус» – это просто гауссово распределение. Всё это является введением в байесовскую перспективу машинного обучения.

Гауссово распределение значений весовых коэффициентов называется приором. Это значит, что оно представляет наши априорные ожидания значений весовых коэффициентов, в частности, они должны быть небольшими и центрироваться в районе нуля, а дисперсия этого гауссового распределения равна 1/λ. Параметр λ также называют точностью модели; он является величиной, обратной дисперсии. Мы будем снова и снова встречаться с ним на протяжении байесовского машинного обучения.

Правило Байеса гласит: апостериор пропорционален правдоподобию, умноженному на приор:

 p (B|A) = \frac {p(A|B) p (B)} {p(A)} = \frac {p (A,B)} {p(A)}.

Следствием этого правила является то, что

\sum_{B}{p (A,B)} = \sum_{B} p(A|B) p (B).

Таким образом, без регуляризации мы ищем максимум функции правдоподобия. Теперь же мы не максимизируем функцию правдоподобия – теперь мы максимизируем апостериор. Этот метод называется вычислением максимума апостериора или, сокращённо, вычислением MAP.

L2-регуляризация. Код

Как вы догадались сейчас пошла практика, где вы научитесь применять регуляризацию в коде.

Мы используем код из предыдущих занятий, поскольку он очень похож, мы лишь добавим компонент регуляризации. Добавим просто константу λ, чьё значение установим равной 0,1, умноженную на значение весовых коэффициентов.

learning_rate = 0.1

for i in xrange(100):

if i % 10 == 0:

print cross_entropy(T, Y)

w += learning_rate *(np.dot((T-Y).T, Xb) – 0.1*w)

Y = sigmoid(Xb.dot(w))

Запустим программу. Как вы можете видеть, теперь значение весовых коэффициентов значительно меньше. Это и даёт регуляризация. Поскольку мы предполагаем, что данные нормально распределены около нуля, мы получаем значения весовых коэффициентов куда ближе к нулю, и они не стремятся расти до бесконечности.

Андрей Никитенко
Андрей Никитенко
Задать вопрос эксперту
Понравилась статья? Поделить с друзьями:
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!:

Share via
Copy link