Обзор одного из самых фундаментальных алгоритмов машинного обучения: алгоритма регрессии

Алгоритм регрессии — один из самых фундаментальных алгоритмов машинного обучения. Неважно, замечаем мы это или нет, на каком-то этапе нашей жизни мы сталкивались с проблемами регрессии. Вы хотите взять такси, чтобы поехать в аэропорт? У вас возникла проблема с регрессией. Вы хотите купить новый дом? Вы снова столкнулись с проблемой регрессии.

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

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

  • Линейная регрессия
  • Метрики регрессии и функции стоимости
  • Нормальное уравнение
  • Градиентный спуск для линейной регрессии
  • Полиномиальная регрессия
  • Компромисс смещения и дисперсии
  • Регуляризованная линейная модель (Регрессия Риджа, Регрессия Лассо, ElasticNet)
  • Опорная векторная регрессия
  • Регрессия дерева решений

Итак, без лишних слов, давайте начнем с самой простой модели из всех — линейной регрессии.

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

1. Линейная регрессия

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

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

Ниже приведено уравнение линейной регрессии в простейшей форме:

где:

ŷ: прогнозируемое значение
θ₀: точка пересечения
θ₁: вес первого предиктора
x₁: значение первого предиктора

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

  • Стоимость проезда на такси как прогнозируемое значение (ŷ)
  • Расстояние между вашим домом и аэропортом как значение предиктора (x₁)
  • Вы можете представить перехват как начальную цену, которую вам нужно заплатить, как только вы сядете в такси. Если вы заметили, стоимость проезда в такси начинается не с 0 всякий раз, когда вы садитесь в такси, а с некоторой цены, скажем, 5 долларов. Эти 5 долларов — это точка пересечения (θ₀).
  • Можно представить вес предсказателя как сумму денег, которую нужно заплатить, как только расстояние, пройденное такси, увеличится на 1 км (θ₁).

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

Чтобы предсказать деньги, которые вам нужно потратить на такси, вам понадобится красная линия ниже:

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

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

2. Метрики регрессии и функции стоимости

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

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

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

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

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

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

Среднеквадратическая ошибка (MSE)

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

где:

N: общее количество точек данных
yi: фактическое значение каждой точки данных
ŷi: значение каждая точка данных, предсказанная линией регрессии

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

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

  1. Чтобы убедиться, что у нас есть положительное значение ошибки
  2. Чтобы «наказать» регрессионную модель, когда ошибка велика

Среднеквадратичная ошибка (RMSE)

Как следует из названия, среднеквадратическая ошибка (RMSE) является расширением MSE. По сути, это просто квадратный корень из MSE, как видно из приведенного ниже уравнения.

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

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

Средняя абсолютная ошибка (MAE)

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

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

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

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

Теперь должен возникнуть естественный вопрос: мы знаем, как измерить качество нашей линии регрессии, но как мы можем ее улучшить? Другими словами, как наша модель может создать линию регрессии, которая минимизирует значение MSE?

Чтобы минимизировать значение MSE, нам нужно обучить нашу модель регрессии на доступных точках данных. Есть два способа минимизировать значение MSE и обучить модель регрессии: использовать нормальное уравнение и использовать алгоритм градиентного спуска.

Мы рассмотрим оба метода и начнем с нормального уравнения.

3. Нормальное уравнение

Нормальное уравнение — это решение в закрытой форме, доступное только в задаче регрессии. С помощью этого уравнения вы можете получить линию регрессии с наилучшей точностью за доли секунды.

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

где:

θ̂: значения веса точки пересечения и каждого предиктора, которые минимизируют функцию стоимости
X: матрица предикторов
y: вектор истинных значений каждой точки данных

По мере увеличения числа предикторов вычисления будут более сложными. Однако мы можем легко вычислить это с помощью Python, как вы можете видеть ниже.

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

# Generate data
np.random.seed(42)
x = 2 * np.random.rand(100,1)
y = 4 + 3 * x + np.random.rand(100,1)

x_b = np.c_[np.ones((100,1)), x] #for intercept

# Compute normal equation
theta_hat = np.linalg.inv(x_b.T.dot(x_b)).dot(x_b.T).dot(y)
print(theta_hat)

# Output: array([[4.51359766],
       [2.98323418]])

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

Наконец, мы можем визуализировать линию регрессии с помощью следующего кода:

# Create regression line
x_new = np.array([[0], [2]])
x_new_b = np.c_[np.ones((2,1)), x_new]
y_new = x_new_b.dot(theta_hat)

# Plot regression line
plt.figure(figsize=(12, 8))
plt.plot(x_new, y_new, 'r-')
plt.plot(x,y,'bd')
plt.xlabel('Distance (km)')
plt.ylabel('Price ($)')

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

x_new = np.array([[1.5]]) # Our distance
x_new_b = np.c_[np.ones((1,1)), x_new]
y_new = x_new_b.dot(theta_hat)

print(y_new)

# Output: array([[8.98844892]])

Как видите, регрессионная модель предсказывает, что нам придется заплатить примерно 9 долларов, если мы хотим взять такси до аэропорта.

Есть два преимущества использования нормального уравнения для поиска наиболее подходящей линии регрессии:

  • Это очень просто реализовать
  • Это очень масштабируемо, если у нас много точек данных (данные для обучения)

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

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

4. Градиентный спуск для линейной регрессии

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

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

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

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

  1. Вычислите градиент функции стоимости относительно веса каждого предиктора.

Или мы можем обобщить приведенное выше уравнение для всех предикторов в следующее уравнение:

где:

j: общее количество предикторов
k: общее количество точек данных

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

2. Обновите вес каждого предиктора, вычтя его из градиента.

Скорость обучения градиентного спуска

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

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

Однако нам нужно понимать преимущества и недостатки этой корректировки скорости обучения:

  • Если скорость обучения слишком мала, то регрессионная модель будет сходиться очень медленно, и вам потребуется больше итераций обучения для градиентного спуска, чтобы достичь глобального минимума.

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

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

Пакетный градиентный спуск

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

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

Ниже приведена реализация пакетного градиентного спуска.

# Set hyperparameters
lr = 0.01
epochs = 3000
train_data = len(x)


# For intercept
X_b = np.c_[np.ones((100,1)), x] 

# Initialize weight
theta = np.random.randn(2,1)

# Gradient descent over whole data
for i in range(epochs):
    
      # Compute the gradient of each predictor
	grad = 2 / train_data * X_b.T.dot(X_b.dot(theta)-y)
      
      # Update the weight of each predictor 
	theta = theta - lr*grad

print(theta)
# Output: array([[4.51354059], [2.98328456]])

# Visualize result

plt.figure(figsize=(12, 8))
plt.plot(x, theta[0][0] + x * theta[1][0], 'r-')
plt.plot(x, y,'bd')
plt.xlabel('Distance (km)')
plt.ylabel('Price ($)') 

И, наконец, у нас есть идеально подобранная линия регрессии!

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

Стохастический градиентный спуск

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

Ниже приведена реализация стохастического градиентного спуска:

epochs = 3000
lr = 0.01

theta = np.random.randn(2,1)

for i in range(epochs):
    
  for j in range(train_data):
   	 
    	# Choose random training data
    	idx = np.random.randint(train_data)
    	x_i = X_b[idx:idx+1]
    	y_i = y[idx:idx+1]
   	 
    	# Compute gradients based on randomly selected training data
    	grad = 2 * x_i.T.dot(x_i.dot(theta) - y_i)
    	theta = theta - lr * grad

print(theta)
# Output: array([[4.4920683 ],[2.98692425]])If you want to have a simpler implementation than the code snippet above, then you can also utilize SGDRegressor method from scikit-learn library.
from sklearn.linear_model import SGDRegressor sgd = SGDRegressor(max_iter=3000, eta0=0.01) sgd.fit(x, y.ravel()) print(sgd.intercept_, sgd.coef_) # Output: [4.1762039] [3.28159362] # Visualize result plt.figure(figsize=(12, 8)) plt.plot(x, sgd.predict(x), 'r-') plt.plot(x, y,'bd') plt.xlabel('Distance (km)') plt.ylabel('Price ($)')

Если вам нужна более простая реализация, чем приведенный выше фрагмент кода, вы также можете использовать метод SGDRegressor из библиотеки scikit-learn.

from sklearn.linear_model import SGDRegressor

sgd = SGDRegressor(max_iter=3000, eta0=0.01)
sgd.fit(x, y.ravel())

print(sgd.intercept_, sgd.coef_)
# Output: [4.1762039] [3.28159362]

# Visualize result
plt.figure(figsize=(12, 8))
plt.plot(x, sgd.predict(x), 'r-')
plt.plot(x, y,'bd')
plt.xlabel('Distance (km)')
plt.ylabel('Price ($)')

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

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

Мини-пакетный градиентный спуск

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

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

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

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

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

5. Полиномиальная регрессия

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

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

np.random.seed(42)
x = 6 * np.random.rand(100, 1)-3
y = 2 * x**2 + np.random.randn(100,1)

plt.figure(figsize=(12, 8))
plt.plot(x, y,'bd')
plt.xlabel('x1')
plt.ylabel('y')

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

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

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

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

Чтобы преобразовать нашу обычную функцию линейной регрессии в функцию полиномиальной регрессии, как указано выше, мы могли бы использовать класс PolynomialFeatures из scikit-learn. Этот класс создаст возможности каждого предиктора в качестве дополнительных предикторов в нашей функции регрессии.

from sklearn.preprocessing import PolynomialFeatures
import operator

poly_features = PolynomialFeatures(degree=2, include_bias=False)
x_poly = poly_features.fit_transform(x)

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

После этого преобразования функции мы можем подобрать модель линейной регрессии для этой преобразованной функции следующим образом:

import operator

lin = LinearRegression()
lin.fit(x_poly, y)

# Sort value before plotting
sort_axis = operator.itemgetter(0)
sorted_zip = sorted(zip(x,lin.predict(x_poly)), key=sort_axis)
x_pred, y_pred = zip(*sorted_zip)


# Visualize the result
plt.figure(figsize=(12, 8))
plt.plot(x_pred, y_pred, 'r-')
plt.plot(x, y,'bd')
plt.xlabel('x1')
plt.ylabel('y')

И теперь у нас есть линия регрессии, которая очень хорошо отражает структуру наших данных!

Если вы хотите узнать больше о полиномиальной регрессии, ознакомьтесь с этим ресурсом.

6. Компромисс смещения и дисперсии

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

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

Это не то, что мы хотим получить от подобранной линии по одной очевидной причине: она плохо обобщает. Мы ожидаем плохой производительности, если предоставим модели невидимую точку данных. И это то, что мы называем переоснащением.

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

  • Недообучение означает, что модель не может зафиксировать шаблон обучающих точек данных.
  • Переобучение означает, что модель пытается подобрать каждую из точек обучающих данных, так что она не будет хорошо обобщать невидимые точки данных.

Если вы понимаете эти два термина, то вы также понимаете такие термины, как предвзятость и дисперсия.

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

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

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

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

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

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

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

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

7. Регуляризованная линейная модель

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

Существует три типа регуляризованной линейной модели, которые обычно применяются на практике: регрессия гребня, регрессия Лассо и эластичная сеть. Начнем с ридж-регрессии.

Ридж-регрессия

Ридж-регрессия имеет дополнительный член в своей функции стоимости по сравнению с обычной линейной регрессией, как вы можете видеть в следующем уравнении:

где:

  • α: гиперпараметр, определяющий степень регуляризации модели линейной регрессии.
  • θi: вес каждого предиктора.

Основная цель этого дополнительного члена — сохранить малые веса нашей модели в процессе обучения.

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

Реализовать Ridge Regression с библиотекой scikit-learn очень просто, как вы можете видеть ниже:

from sklearn.linear_model import Ridge

ridge = Ridge(alpha=1)
ridge.fit(x,y)

Лассо-регрессия

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

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

Интуиция остается такой же, как и у Ридж-регрессии. Если вы установите α равным нулю, мы получим обычную линейную регрессию. Между тем, если мы установим α на большое число, то получим плоскую линию, которая проходит через среднее значение наших данных.

Чтобы реализовать регрессию Лассо с помощью scikit-learn, мы можем сделать следующее:

from sklearn.linear_model import Lasso

lasso = Lasso(alpha=0.1)
lasso.fit(x,y)

Ознакомьтесь с этим ресурсом, если хотите узнать больше о регрессии гребня и регрессии лассо!

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

Эластичная сеть может рассматриваться как комбинация регрессии хребта и регрессии лассо, как вы можете видеть в уравнении функции стоимости ниже.

Из приведенного выше уравнения у нас есть один дополнительный член, называемый , который является нашим коэффициентом I . Если вы установите соотношение I равным 1, то у нас будет чистая регрессия Лассо. Между тем, если вы установите отношение I равным 0, то у нас будет чистая регрессия хребта.

Внедрение Elastic Net с помощью scikit Learn так же просто, как и две другие регуляризованные линейные модели, как вы можете видеть ниже.

from sklearn.linear_model import ElasticNet

elastic_net = ElasticNet(alpha=1, l1_ratio=0.5)
elastic_net.fit(x, y) 

8. Регрессия машины опорных векторов (регрессия SVM)

Машина опорных векторов (SVM) — это алгоритм машинного обучения, который чаще используется для задач классификации. Фундаментальный принцип алгоритма SVM заключается в создании гиперплоскости для разделения точек данных с наибольшим запасом. В качестве примера рассмотрим следующие точки данных:

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

Оказывается, мы можем использовать описанную выше концепцию для решения проблемы регрессии. Разница в следующем:

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

Сама концепция регрессии SVM также отличается от типичного алгоритма регрессии на основе градиентного спуска, такого как регрессия гребня, регрессия Лассо и эластичная сеть выше.

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

Чтобы реализовать линейную регрессию с регрессией SVM, вы можете использовать библиотеку scikit-learn следующим образом:

from sklearn.svm import SVR

np.random.seed(42)
x = 2 * np.random.rand(100,1)
y = 4 + 3 * x + np.random.rand(100,1)

svr = SVR(kernel = 'linear', epsilon = 0.1)
svr.fit(x,y.ravel())

# Plot result
plt.figure(figsize=(12, 8))
plt.plot(x, svr.predict(x), 'r-')
plt.plot(x,y,'bd')
plt.xlabel('x1')
plt.ylabel('y')

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

svr = SVR(kernel = 'poly', degree= 2)
svr.fit(x,y.ravel())

Если вы хотите узнать больше о теории регрессии опорных векторов, ознакомьтесь с этим ресурсом.

9. Регрессия дерева решений

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

Дерево решений состоит из трех частей: корневой узел, внутренний узел и лист. node, как показано на изображении ниже.

Для каждой из наших точек данных он проходит от корневого узла до конечного узла, отвечая на ряд условий True или False во внутренних узлах. Наконец, конечный узел даст результат каждой из наших точек данных.

Концепция дерева решений для классификации и регрессии аналогична. Единственное отличие:

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

Как вы можете видеть ниже, реализовать регрессию дерева решений с помощью scikit-learn очень просто.

from sklearn.tree import DecisionTreeRegressor

np.random.seed(42)
x = 2 * np.random.rand(100,1)
y = 4 + 3 * x + np.random.rand(100,1)

tree = DecisionTreeRegressor()
tree.fit(x, y)

# Visualize regression line
x_grid = np.arange(min(x), max(x), 0.01)
x_grid = x_grid.reshape((len(x_grid), 1))
plt.figure(figsize=(12, 8))
plt.plot(x_grid, tree.predict(x_grid), 'r-')
plt.plot(x,y,'bd')
plt.xlabel('x1')
plt.ylabel('y')

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

Это переоснащение обычно происходит, когда мы устанавливаем для всех гиперпараметров значения по умолчанию (т. е. мы не указываем максимальную глубину дерева). Чтобы избежать этого, мы можем поиграть с параметром max_depth при инициализации модели с помощью scikit-learn.

from sklearn.tree import DecisionTreeRegressor

tree = DecisionTreeRegressor(max_depth=3)

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

Если вы хотите увидеть визуализацию этого алгоритма регрессии дерева решений, ознакомьтесь с этим ресурсом.

Заключение

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

Основная цель этих алгоритмов машинного обучения — создать линию регрессии, которая минимизирует нашу функцию стоимости или показатели, такие как MSE, RMSE или MAE.

Готовы ли вы создать свой собственный регрессионный проект? Вам могут помочь следующие ресурсы:

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

Первоначально опубликовано на https://www.stratascratch.com.