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

Зачем нужна регуляризация?

Регуляризация — это стратегия, используемая в машинном обучении для борьбы с переоснащением. Переобучение происходит, когда наша модель слишком хорошо соответствует нашему обучающему набору данных. К сожалению, хорошая работа с обучающими данными не обязательно означает, что модель будет хорошо соответствовать невидимым данным. На самом деле часто бывает с точностью до наоборот. Когда модель очень хорошо соответствует обучающим данным, это обычно означает, что она улавливает слишком много шума или вариации в точках данных, которые либо случайны, либо нерелевантны. Это может привести к тому, что модель зациклится на более мелких особенностях обучающих данных, которых на самом деле нет в невидимых наборах данных. И поскольку сила моделей машинного обучения заключается в их способности предсказывать, а не просто сообщать нам то, что мы уже знаем, мы отдаем приоритет тому, насколько хорошо модель соответствует невидимым данным, а не обучающим данным. Так как же нам убедиться, что наши модели не настолько точно соответствуют нашим обучающим данным, что они теряют способность обобщать? Вот где регуляризация пригодится!

Понимание регуляризации:

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

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

Потеря = MSE + регуляризация

Фактический расчет этого члена регуляризации будет зависеть от того, какой метод вы применяете к своей модели. Три основных метода регуляризации: L1 (лассо), L2 (конек) и эластичная сеть.

Регуляризация L1 (лассо):

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

#import relevant functions 
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import Lasso
from sklearn.metrics import mean_squared_error
from sklearn.datasets import load_diabetes
from sklearn.preprocessing import StandardScaler

#load in dataset
data = load_diabetes(return_X_y=True, as_frame=True)
X = data[0]
y = data[1]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.25, random_state=42)

#standard scale data 
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

#instantiate and fit Lasso Regression
lasso = Lasso(alpha=1)
lasso.fit(X_train_scaled, y_train)

#R2 scores for train and test data 
train_r2 = lasso.score(X_train_scaled, y_train)
test_r2 = lasso.score(X_test_scaled, y_test)

print(train_r2, test_r2)

Регуляризация L2 (хребет):

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

Гребневая регрессия уменьшает коэффициенты и помогает справиться со сложностью и коллинеарностью модели.

#import relevant packages
from sklearn.linear_model import Ridge
from sklearn.datasets import load_diabetes
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error
import pandas as pd

#load data as dataframe
data = load_diabetes(return_X_y = True, as_frame = True)
X = data[0]
y = data[1]

#perform train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.25, random_state=42)

#instantiate, fit, transform Standard Scaler
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

#instantiate Ridge Regression, fit on training data
ridge = Ridge(alpha=100)
ridge.fit(X_train_scaled, y_train)

#assess train and test scores
train_score = ridge.score(X_train_scaled, y_train)
test_score = ridge.score(X_test_scaled, y_test)

print(f"Train Score: {train_score}")
print(f"Test Score: {test_score}")

y_pred_test = ridge.predict(X_test_scaled)
y_pred_train = ridge.predict(X_train_scaled)

train_mse = mean_squared_error(y_train, y_pred_train)
test_mse = mean_squared_error(y_test, y_pred_test)

print(f"Train MSE: {train_mse}")
print(f"Test MSE: {test_mse}")

Эластичная сетка:

Elastic Net эффективно сочетает в себе как Lasso, так и Ridge, чтобы использовать сильные стороны обоих. Он добавляет к функции потерь линейную комбинацию штрафов L1 и L2, которую можно настроить, изменив параметр l1_ratio класса ElasticNet(). Полученная функция потерь выглядит примерно так:

elastic_net_regularization = (альфа * L1_regularization) + ((1-альфа) * ​​L2_regularization)

#import relevant functions 
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import ElasticNet
from sklearn.metrics import mean_squared_error
from sklearn.datasets import load_diabetes
from sklearn.preprocessing import StandardScaler

#load in dataset
data = load_diabetes(return_X_y=True, as_frame=True)
X = data[0]
y = data[1]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.25, random_state=42)

#standard scale data 
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

#instantiate and fit Elastic Net
en = ElasticNet(alpha=.1, l1_ratio=.5)
en.fit(X_train_scaled, y_train)

#R2 scores for train and test data 
train_r2 = en.score(X_train_scaled, y_train)
test_r2 = en.score(X_test_scaled, y_test)

print(train_r2, test_r2)

Хотя существует множество нюансов и стратегий использования регуляризации, знание основных идей L1, L2 и Elastic Net значительно расширит ваши возможности настройки модели. Когда у вас будет базовый код, вы можете продолжить настройку альфы, L1_ratio и других аспектов регуляризации, чтобы получить лучшую модель!