Drive your career as React Developer with Symphony Solutions!
×Закрыть

Регуляризация: что это и почему важно

Автор: Богдан Цал-Цалко, data scientist в DataRobot, лектор онлайн-школы robot_dreams.

Переобучение часто возникает при попытках улучшения datascience-моделей. Чем больше параметров, тем проще совершить эту ошибку. Я более 8 лет работаю с данными, и знаю, что при создании сложных моделей всегда нужно использовать инструменты, ограничивающие переобучение.

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

Статья будет полезна аналитикам данных, которые хотят научиться работать с более сложными моделями.

Материал будет легче воспринять тем, кто уже знаком с линейной регрессией. Рассказывать о ней и о других основных типах регрессии я буду на своем курсе «Математика и статистика для анализа данных» в robot_dreams.

В каких случаях нужна регуляризация

Понять, как возникает переобучение, поможет пример.

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

L(a) = L(1-e-k(a-a0))


Где:

а — возраст рыбы (наша единственная фича)

а0- константа для оценки веса рыбы при рождении (допустим, — 0,47)

k — коэффициент скорости роста (допустим, 0,52)

L- асимптотический вес (допустим, 2,75 кг)

Смоделируем ферму:

import sklearn.linear_model as lm
import numpy as np
import matplotlib.pyplot as plt

a0 = - 0.47
k = 0.52
L_inf = 2.75

N = 1000 #кол-во выловленной рыбы
min_age = 0.3
# сгенерируем возраст выловленной рыбы экспоненциально
a = np.random.exponential(1,N)+min_age
L_a = L_inf*(1-np.exp(-k*(a-a0))) + np.random.normal(0,a/10,N)
a = a[L_a>0]     # выжила только рыба с положительным весом
L_a = L_a[L_a>0] # выжила только рыба с положительным весом
plt.plot(a[L_a>0], L_a, '.b', alpha=0.3)

Теперь смоделируем вес рыб в зависимости от возраста с помощью линейной регрессии:

def RMSE(predicted, actual):
    return np.sqrt(np.mean((predicted-actual)**2))

reg1 = lm.LinearRegression()
reg1.fit(np.reshape(a,[-1,1]), L_a)
plt.plot(a[L_a>0], L_a, '.b', alpha=0.3)
a_sample = np.arange(min_age, max(a), (max(a) - min_age)/100 )
predictions = reg1.predict(np.reshape(a_sample,[-1,1]))
plt.plot(a_sample, predictions, 'r')
plt.show()
print(f'RMSE: {RMSE(reg1.predict(np.reshape(a,[-1,1])),L_a)}')

Полученная RMSE (среднеквадратическая ошибка модели) на обучающих данных равна 0,30. Мы специально используем результаты на обучающей выборке, чтобы узнать, какова ее способность противостоять переобучению.

Видим, что зависимость явно не линейная, поэтому мы попробуем добавить полиномиальность в регрессию.

def poly_feature(feat, power):
    features = [feat]
    for i in np.arange(2,power+1):
        features.append(feat**i)
    return np.array(features).T

for power in np.arange(2,11):
    a_poly = poly_feature(a,power)
    reg1.fit(a_poly, L_a)
    print(f'RMSE for power {power}: {RMSE(reg1.predict(a_poly),L_a)}')
RMSE for power 2: 0.19685306265029515
RMSE for power 3: 0.18542068046311963
RMSE for power 4: 0.18531090269033101
RMSE for power 5: 0.18530908506583935
RMSE for power 6: 0.18525464737647415
RMSE for power 7: 0.184936989050177
RMSE for power 8: 0.18471195775479393
RMSE for power 9: 0.18466928989570355
RMSE for power 10: 0.18428989851761335
power = 10
reg1.fit(poly_feature(a,power), L_a)
plt.plot(a[L_a>0], L_a, '.b', alpha=0.3)
a_sample = np.arange(min_age, max(a), (max(a) - min_age)/100 )

plt.plot(a_sample, reg1.predict(poly_feature(a_sample,power)), 'r')
plt.xlabel('Age')
plt.ylabel('Weight')

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

Начиная с возраста 7, по нашим оценкам, у рыб может наблюдаться отрицательный вес. Этот искусственный пример наглядно показывает, как работает переобучение в data science.

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

В чем суть регуляризации

Мы будем «наказывать» модель за избыточную сложность. Тут на помощь приходит регуляризация. Для линейной регрессии её идея проста и универсальна: добавить к оценке качества модели — функции потерь — сумму её собственных коэффициентов

Функция потерь обычной линейной регрессии:

Лассо-регрессия (lasso regression) — линейная регрессия с линейной пенализацией коэффициентов:

Ридж-регрессия (ridge regression) — регрессия с квадратичной пенализацией коэффициентов:

Эластик-нет (elastic net) — комбинация ридж-регрессии и лассо-регрессии:

где:

α — это коэффициент который отвечает за влияние регуляризации.

l1 ratio — коэффициент пропорции двух пенализаций в elastic net


Чтоб понять, как подобрать, нужно учитывать, что при:

α→0 мы получаем обратную линейную регрессию

α→∞ мы получаем среднее вместо регрессии

Технически минимизация таких регрессий немного сложнее — в отличие от обычной регрессии, у них нет прямых решений,. Для их решения часто прибегают к градиентному спуску (почти нейронная сеть).

Особенности работы с регуляризацией:

  1. Функция потерь с учетом регуляризации нужна только для подбора коэффициентов. Нельзя сравнивать функции потерь разных моделей.
  2. Результаты обычных метрик на тренировочных данных будут уступать таковым для линейной регрессии. Это нормально. Наша цель — добиться за счет этого лучшей генерализации знаний из данных и повысить точность на валидационных данных.
  3. Признаки (features) должны быть нормированы или стандартизированы.

В обычной линейной регрессии единица измерения признака (килограммы или граммы) не имеет значения. Но если в моделях с регуляризацией один из признаков будет измеряться в килограммах, а другой — в граммах, то коэффициенты при них будут по-разному влиять на оптимизацию функции потерь. Соответственно, переменная в граммах может оказаться важнее. Я предпочитаю использовать стандартизацию данных при α не больше, чем стандартное отклонение целевого признака.

Посмотрим на примере рыбной фермы, как бы себя повела линейная регрессия с регуляризацией:

from sklearn.preprocessing import StandardScaler
lasso = lm.Lasso(0.01)
power = 10
scaler = StandardScaler()

a_processed = poly_feature(a,power)
a_processed = scaler.fit_transform(a_processed)

lasso.fit(a_processed, L_a)
plt.plot(a[L_a>0], L_a, '.b', alpha=0.3)

a_sample = np.arange(min_age, max(a), (max(a) - min_age)/100 )
a_sample_processed= scaler.transform(poly_feature(a_sample,power))

plt.plot(a_sample, lasso.predict(a_sample_processed), 'r')
plt.xlabel('Age')
plt.ylabel('Weight')

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

Для ридж-регрессии получается более гладкая кривая, которая лучше описывает левый край:

Регуляризация для деревьев принятия решений

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

В семье моделей на основе деревьев принятия решений одно дерево способно выучить все данные. Это приводит к сильному переобучению. Поэтому стратегии регуляризации для них встроены в большинство популярных пакетов. Эти стратегии часто заключаются в ограничении определенных параметров дерева:

  • Глубина дерева — параметр, который ограничивает максимальный рост дерева (деревья принятия решений растут в глубину). Этот параметр позволяет уменьшить переобучение, но ограничивает количество переменных для каждого конкретного листа.
  • Минимальный вес листа — параметр, который ограничивает рост дерева, когда следующее деление листа приводит к тому, что хотя бы в одном из них слишком мало наблюдений, что делало бы его слишком специфичным.

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

Леса деревьев принятия решений — более сложная модель. Для нее настраиваются параметры регуляризации, которые встречаются во многих нейросетях и являются универсальными для большинства итеративных моделей обучения:

  • Скорость обучения (learning rate) — коэффициент, который показывает, насколько подробно нужно уточнять свои результаты с каждым шагом. Если сделать его слишком низким, то понадобится больше итераций, чтобы прийти к хорошему решению. Но есть риск, что остановиться вовремя не получится, и модель выучит данные слишком подробно, что приведет к переобучению. Если же, напротив, этот параметр будет слишком высоким, модель сможет выйти на хорошую точность за меньшее количество итераций. Но ей будет сложно приблизиться к лучшему результату, и она останется недообученной.
  • Отсев (dropout) — параметр, которым задается относительная часть всех данных, скрытая случайным образом во время обучения.

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

  • Ранняя остановка (early stopping) — это стратегия, при которой мы возвращаемся к последней лучшей итерации в случае, если после нескольких итераций подряд точность модели на скрытых валидационных данных не улучшилась. Это универсальный метод. Чтобы его применять, нужно достаточное количество валидационных данных для обучения.

Почему регуляризованные модели работают лучше обычных

В моем опыте работы с платформой автоматического машинного обучения DataRobot ridge-регрессия и elastic net зарекомендовали себя гораздо лучше обычной регрессии.

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

Регуляризация — это защитный механизм алгоритмов обучения от избыточной сложности. Он помогает избежать переобучения. Это понятие объединяет множество инструментов и стратегий, и цель их всех — помочь автоматизировать войну data science против переобучения.

LinkedIn
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Я наискосок прочитал, но посмотрел на два последних графика, из которых я могу сделать два разных вывода 1) итоговые модели неправильные — рыбы растут, они же не могут с 6-го года жизни вдруг худеть :) просто интересно, а как вы в итоге довели модель до нормального вида, есть итог с графиком? 2) вы на своей модели доказали вред ожирения, толстые рыбы долго не живут? 😁 Что делаете, когда у модели могут быть разные интерпретации, статистически все ок, но здравый смысл подсказывает, что что-то не то, что делаете в таких ситуациях?

1) Целью статьи было разобрать как регуляризация ограничивает переобучение, в итоговых моделях я это и демонстрирую. Как проект это воспринимать не стоит хотя бы по той причине, что я не выделяю данных для валидации. Именно валидация смогла бы продемонстрировать описанные вами проблемы
2) В формуле фон Берталанфи есть ограничение по весу сверху, с определнного момента рыбы перестают рости. В моделировании нету ограничения по возрасту.
3) Всегда первоочередным является здравый смысл. Статистика не имеет мнения, это лишь инструмент для подтверждения или опревержения чужих идей. Если статистика будет основываться на ложных идеях то и результаты будут соответствующие.

а чому ціни на курси не вказані?

Приятно читать было. Кратко, четко и по сути. Было бы еще хорошо, если бы добавил ссылок-посыланий для тех, кто темой и ее применением заинтересуется.

Он заботливо ссылку на свой курс приложил :)

Ну че? Молодец — написал ненапрягающую рекламную статью своего курса.

L_a = L_inf*(1-np.exp(-k*(a-a0))) + np.random.normal(0,a/10,N)

Така гаусова рандомізація, еквівалентна рандомізації параметра L_inf.
Чому б не рандомізовувати ще й k i a0?
Розподіл би вийшов ближче до спостережуваного.

α→0 мы получаем обратную линейную регрессию

В якому розумінні зворотню? Ми отримуємо звичайну лінійну регресію.

Така гаусова рандомізація, еквівалентна рандомізації параметра L_inf.

1 сумніваюся
2 канонічна форма: лейбл = шукома функція + irreducible error

В відомій формулі

шукома функція + irreducible error

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

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

Чи не були б ви такі ласкаві нагадати мені, тип сходимості, до чого саме воно сходиться і теорему з якої одразу випливає чому сходиться?

Ладно, прогнав — правильно українською казати «збіжність»

Ви мені нагадуєте Junior Developer з dou.ua/...​d-growing-potato/#1953969
Молодші внучки бігають по городу, кидаються грудками один в одного і при першій же нагоді тікають у тіньок або пограти у футбол. На них кричить мама, сердиться старший брат, але ніхто сильно не гримає, бо розуміє, що вони ще діти. Це Junior Developers.

Ой діду, не кряхти. Краще розкажи як на твою думку L_inf може бути розподілений

1) Хорошее предложение, но я решил заложить эти все нюансы в параметризованное отклонение ошибки, которое зависит линейно от а/10
2) Очепятка, правильно — «обратно получаем линейную регрессию»

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

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

Вот заложил бы ты в свою модель ЦЕЛЕВОЙ показатель, а именно, параметры нормального распределения и формулу, и получил бы требуемое предсказание. В частности, понимал бы, какие данные полагается отстреливать (если они не важны для результата как отдельное слагаемое или фактор), и какая статистика по отстрелу должна дать алерт что модель попала на непредсказуемые данные.

Почему так: именно алерты и являются основной ценностью машинной логики. Человек умеет анализировать, но он не умеет этого 24/7, а машина умеет. Задача машины — не просто предсказывать прогноз, а ещё и сравнивать реальную статистику, тем самым экономя время человека там, где статистика не показывает аномалий.

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

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

Людям тяжелее понять что они ошибаются, и по этому «проще».

Хотел бы я посмотреть (а заодно и почятиться) на не супер-Тьюринг полную вычислительную систему, которая в принципе может понять вычислить, что она ошибается!

С саппортом Приватбанка пообщайся, там такая выдрессерованная тьюринг-машина, что ты предпочтёшь трепаться с ботами — они по крайней мере не врут абы что, лишь бы от тебя сдыхаться (и передать тебя другому оператору).

Та не, то известно шо супер-тьюринг полные потомки гоминид с подтюненым церебрал процессинг юнитом

Окупейшнл хазард удачно лёгший на смесь личностных качеств и способностей

— Мам, я не курил, просто стоял где курили
— Сидел где пили, лежал где сексом занимались

Проклятый Приватбанк, только со второго раза удалось поговорить с живым человеком.

Кто общался с живым саппортом Алиэкспресса — квест привата проходит с закрытыми глазами.

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

Что ошибся другой человек понять на удивление легко

истинометр одолжите, мне бы очень пригодился.

тем самым ловить аномалию подделки показателей через потерю их статистической связанности или предсказуемости.

Наприклад вибори в Росії і Білорусі.

Чи в Україні. Тут не було жодних виборів без масових фальсифікацій за всю історію.

Что за Зеленского 99% проголосовали, а он себе только 80% написал?

Останні значимо фальсифіковані це другий тур Янукович-Ющенко, 16 років тому.
А зараз так, незначні статистичні флюктуації.

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

А по Зельцю... киданули Йулю. Саме «вона», а не Пєтя, виходила в другий тур. Але вона недоплатила своїй команді, і її пірамідки перекупив Пєтюля. Не допомогло.

Фальсифікації доводяться строго математично. Читай уважно arxiv.org/pdf/1204.0307.pdf
Особливо в Росії люблять фальсифікувати без знань статистики та теорії ймовірності. В Білорусі взагалі малюють.

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

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

судя по графику, 3х годичная рыбка размножилась и достигла товарного размера, местные, охранники, и прочие браконьеры начали ее потихоньку вылавливать, при условии что не будут воровать рыбу не товарного размера то рыба больше 3кг просто не может вырасти(но и не будет полностью выловлена), вывод.
сменить и усилить охрану, провести обучение заново, искать баг в определении возраста рыбы(вероятно он привязан к времени зарыбливания)

Надо иногда отправлять охрану кормить рыбок

написано очень неоднозначно, толи охранник кормящий, толи охранник корм))))

Спасибо! Отличный туториал!

Подписаться на комментарии