Регуляризация: что это и почему важно
Автор: Богдан Цал-Цалко, data scientist в DataRobot, лектор онлайн-школы robot_dreams.
Переобучение часто возникает при попытках улучшения datascience-моделей. Чем больше параметров, тем проще совершить эту ошибку. Я более 8 лет работаю с данными, и знаю, что при создании сложных моделей всегда нужно использовать инструменты, ограничивающие переобучение.
Регуляризация — это один из таких инструментов; своего рода встроенный предохранитель. В материале мы рассмотрим на примере, какова природа переобучения, как регуляризация помогает с ним справиться, а также как ее использовать для линейной регрессии и деревьев принятия решений.
Статья будет полезна аналитикам данных, которые хотят научиться работать с более сложными моделями.
Материал будет легче воспринять тем, кто уже знаком с линейной регрессией. Рассказывать о ней и о других основных типах регрессии я буду на своем курсе «Математика и статистика для анализа данных» в robot_dreams.
В каких случаях нужна регуляризация
Понять, как возникает переобучение, поможет пример.
Допустим, у нас есть ферма по выращиванию рыбы одного вида. Когда мы вылавливаем рыбу, то взвешиваем ее. Также можно допустить, что мы знаем возраст каждой пойманной рыбы. Предположим, что мы хотим оценить зависимость ее веса от возраста. Воспользуемся тем что этот биологический процесс был хорошо исследован, и мы сможем сгенерировать нужные нам данные. Обратимся к формуле роста фон Берталанфи:

Где:
а — возраст рыбы (наша единственная фича)
а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 мы получаем обратную линейную регрессию
α→∞ мы получаем среднее вместо регрессии
Технически минимизация таких регрессий немного сложнее — в отличие от обычной регрессии, у них нет прямых решений,. Для их решения часто прибегают к градиентному спуску (почти нейронная сеть).
Особенности работы с регуляризацией:
- Функция потерь с учетом регуляризации нужна только для подбора коэффициентов. Нельзя сравнивать функции потерь разных моделей.
- Результаты обычных метрик на тренировочных данных будут уступать таковым для линейной регрессии. Это нормально. Наша цель — добиться за счет этого лучшей генерализации знаний из данных и повысить точность на валидационных данных.
- Признаки (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 против переобучения.
43 коментарі
Додати коментар Підписатись на коментаріВідписатись від коментарів