Введение

Это подробное руководство по задачам регрессии в рамках машинного обучения с учителем.

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

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

Существует два основных типа задач контролируемого обучения:

  • Задачи регрессии (что мы будем здесь изучать)
  • Классификация задач

В задачах регрессии переменная ответа - потенциальный результат алгоритма, следовательно, зависимая переменная Y - непрерывна.

В задачах классификации переменная ответа дискретна.

Терминология

Целевая переменная относится к нашей зависимой переменной Y.

Переменные функции или простые функции, относятся к нашим независимым переменным X.

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

Уравнение обобщенной регрессии

Функция потерь

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

Остаточная сумма квадратов

Остаточная сумма квадратов (RSS), также известная как сумма квадратов остатков (SSR) или сумма квадратов оценки ошибок (SSE), представляет собой сумму квадратов остатков (отклонения, предсказанные от фактических эмпирических значений данных) . Это мера расхождения между данными и моделью оценки, такой как линейная регрессия. Небольшой RSS указывает на точное соответствие модели данным.

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

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

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

  • Норма Евклидова расстояния (L2 Norm), которая будет использовать длину каждой из наших линий между фактическим результатом и линией, которую мы предсказали (т.е. получение величины этих линий по фактическому расстоянию):

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

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

Контур обучения с учителем

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

  • Возьмите необработанные данные и затем выполните для них извлечение функций / проектирование функций, это будет представлять нашу переменную X.
  • Объедините его с данными с метками, которые будут представлять нашу переменную Y.
  • Используйте данные для обучения модели
  • Затем модель оценивается на основе ее точности в выборке (обучения) и потерь, чтобы увидеть, какие параметры модели необходимо изменить.
  • Наконец, мы оцениваем и набор вне выборки (набор для тестирования), предоставляя модели новые данные, предоставляя входные функции, а затем модель дает нам ожидаемые метки

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

Задачи регрессии на практике

Мы рассмотрим следующие темы:

  1. Исследовательский анализ данных
  2. Функциональная инженерия
  3. Поезд-тестовый сплит
  4. Перекрестная проверка
  5. Настройка гиперпараметров с помощью регрессий Ridge и LASSO с использованием GridSearchCV

1. Исследовательский анализ данных

Цель этого шага - получить представление о типе данных, с которыми мы работаем, их форме и типах данных.

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

По форме данных видно, что у нас есть 1379 наблюдений и 80 столбцов.

Number of rows in the data: 1379
Number of columns in the data: 80

Что нас интересует, так это типы данных для каждого из этих столбцов.

Типы данных для каждого столбца

Затем мы исследуем тип значения, который имеет каждый столбец:

Есть три возможных разных типа:

  • целые числа (int64)
  • с плавающей точкой (float64)
  • строки (объект), представляющие категориальные данные

1. Количественные столбцы: содержат int64 и float64.

2. Категориальные столбцы: содержат объект и нуждаются в преобразовании в одну горячую кодировку или фиктивную переменную.

value_counts () возвращает количество уникальных значений в этом столбце.

data.dtypes.value_counts()

Это вернет сводку всех типов данных в нашем наборе данных, а именно:

object     43
float64    21
int64      16
dtype: int64

2. Разработка функций

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

2.1 Кодирование

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

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

  • Номинальные: категориальные переменные, которые принимают значения в неупорядоченных категориях (например, красный, синий, желтый; истина, ложь; да, нет).
  • Порядковые: категориальные переменные, которые принимают значения в упорядоченных категориях (например, высокий, средний, низкий).

Подходы к кодированию переменных:

а. Двоичное кодирование: преобразует переменные в 0 или 1 и подходит для переменных, которые принимают два возможных значения (например, Истина, Ложь; Мужчина, Женщина; Женат, Не женат).

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

например переменные столбца (красный, синий, зеленый) = ›красный столбец (истина, ложь), синий столбец (истина, ложь), зеленый столбец (истина, ложь)

c. Порядковое кодирование: включает преобразование упорядоченных категорий в числовые значения, обычно путем создания одной переменной, которая принимает целые числа, равные количеству категорий (например, 0,1,2, ..; например, для низкого, среднего и высокого).

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

Здесь мы сосредоточимся на горячем кодировании:

Одно горячее кодирование

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

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

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

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

Это вернет матрицу единиц и нулей для каждой категориальной переменной в нашем наборе данных:

2.2 Преобразование цели

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

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

Как мы можем определить, нормально ли распределена наша цель? Есть два пути:

  • Визуально
  • Использование статистического теста
data.dtypes.value_counts()plt.figure(figsize=(12,5))
data.SalePrice.hist(bins=100)
plt.show()

Мы ясно видим, что цель не имеет нормального распределения, и мы также можем проверить это с помощью статистического теста под названием D’Agostino K² Test:

Это статистический тест, который проверяет, нормально ли распределено распределение. Это не идеально, но достаточно сказать:

  • Этот тест выдает «p-значение». Чем выше это p-значение, тем ближе распределение к нормальному.
  • Статистики-частники сказали бы, что вы согласны с тем, что распределение является нормальным (точнее: не можете отвергнуть нулевую гипотезу о том, что это нормально), если p> 0,05.
from scipy.stats.mstats import normaltest
if normaltest(data.SalePrice.values)[1] > 0.05: 
    print("Normally Distributed\n\n", normaltest(data.SalePrice.values))
else:
    print("Not Normally Distributed\n\n", normaltest(data.SalePrice.values))

Что выведет:

Not Normally Distributed

 NormaltestResult(statistic=594.3267259061613, pvalue=8.781955774010152e-130)

Поэтому мы можем попытаться преобразовать наши данные с помощью:

Журнал-трансформация

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

plt.figure(figsize=(12,5))
log_target = np.log(data.SalePrice)
log_target.hist(bins=50);
plt.show()

2.3 Масштабирование функций

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

Стандартное масштабирование:

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

Мин-макс масштабирование:

Преобразует переменные в непрерывные переменные в интервале (0,1), сопоставляя минимальные значения с 0 и максимальные значения с 1. Этот тип масштабирования чувствителен к выбросам.

Надежное масштабирование:

аналогично масштабированию min-max, но вместо этого отображает межквартильный диапазон (75-75-й процентиль минус 25-25-й процентиль) в (0,1). Это означает, что сама переменная принимает значения за пределами интервала (0,1).

N.B. это часть модуля предварительной обработки sklearn - from sklearn.preprocessing import (StandardScaler, MinMaxScaler, RobustScaler)

Основываясь на этих результатах,

Мы можем «заархивировать» имена функций DataFrame df с моделью model, установленной на этом DataFrame, используя:

pd.DataFrame(zip(X.columns, lr2.coef_)).sort_values(by=1).head()

2.4 Полиномиальная регрессия и эффекты взаимодействия

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

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

from sklearn.preprocessing import PolynomialFeatures

polyFeat = PolynomialFeatures(degree=2)
polyFeat = polyFeat.fit(X_data)
X_ploy = polyFeat.transform(X_data)

Недостатки полиномиальных функций

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

2. 5 Преобразование журнала для перекошенных элементов

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

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

3. Сплит-тест

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

  • Обучение: 70% данных будет использовано для обучения.
  • Тестирование: 30% данных будет использоваться для тестирования.

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

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

4. Перекрестная проверка

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

Ошибка против компромисса сложности

Следовательно, перекрестная проверка может сообщить нам о переоснащении или недостаточном подборе

Компромисс смещения против отклонения

  • Предвзятость: склонность упускать
  • Дисперсия: склонность к непоследовательности.
  • Тенденция: ожидание поведения вне выборки по множеству выборок обучающего набора.

а. Высокое смещение - низкая дисперсия

Склонность прогнозов не соответствовать истинным значениям.

  • Ухудшается из-за отсутствия информации или излишне упрощенных предположений
  • Пропущенные реальные закономерности (недостаточная подгонка)

б. Низкое смещение - высокая дисперсия

Склонность прогнозов к колебаниям

  • Характеризуется чувствительностью выхода к незначительным изменениям входных данных.
  • Часто из-за слишком сложных или плохо подогнанных моделей

Визуализация компромисса сложности

Мы будем использовать объект KFold в SciKit, чтобы научиться сообщать перекрестной проверке, как разделить данные

Pipeline и cross_val_predict

Pipeline позволяет объединить несколько операторов в ваши данные, у обоих есть метод fit.

s = StandardScaler()
lr = LinearRegression()

Объедините несколько этапов обработки в Pipeline

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

estimator = Pipeline([("scaler", s),
                      ("regression", lr)])predictions = cross_val_predict(estimator, X, y, cv=kf)
r2_score(y, predictions)

cross_val_predict

cross_val_predict - это функция, которая выполняет K-кратную перекрестную проверку для нас, соответствующим образом подбирая и преобразуя на каждом этапе пути.

predictions = cross_val_predict(estimator, X, y, cv=kf)
r2_score(y, predictions)
0.7831309631117962

N.B. cross_val_predict не использует одну и ту же модель для всех этапов; прогнозы для каждой строки делаются, когда эта строка находится в наборе проверки. У нас действительно есть собранные результаты 3 (т.е. kf.num_splits) разных моделей.

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

5. Настройка гиперпараметров и регрессии гребня и LASSO с использованием CV

Определение

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

Механика

Мы можем сгенерировать экспоненциальный диапазон значений с помощью функции numpy geomspace.

np.geomspace(1, 1000, num=4)

производит:

array([    1.,    10.,   100.,  1000.])

Используйте эту функцию для создания списка длиной 10 с именем alphas для настройки гиперпараметров:

array([    1.,    10.,   100.,  1000.])
alphas = np.geomspace(1e-9, 1e0, num=10)

Получите разделение данных на Train-Test:

train, test = train_test_split(df, test_size=0.3, random_state=42)
feature_cols = [x for x in train.columns if x != 'SalePrice']
X_train = train[feature_cols]
y_train = train['SalePrice']
X_test  = test[feature_cols]
y_test  = test['SalePrice']

Затем мы настраиваем гиперпараметр alpha для регрессий Лассо или Риджа.

5.1 Регрессия хребта

Функция стоимости регрессии Риджа:

N.B. 𝜆 - это то же самое, что 𝛼 в SciKit Learn

Там, где мы добавляем штраф, коэффициент, который является функцией наших коэффициентов.

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

Масштабирование

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

Стандартное масштабирование можно выполнить следующим образом:

Штраф за регрессию за гребень

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

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

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

Штраф уменьшает величину всех коэффициентов

Большие коэффициенты строго наказываются из-за возведения в квадрат - большие веса наказываются еще более пропорционально меньшим весовым коэффициентам.

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

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

  • Подберите обычную (не прошедшую перекрестную проверку) модель гребня к диапазону значений α и постройте RMSE, используя созданную вами выше функцию перекрестной проверки ошибок.
  • Используйте [0.005,0.05,0.1,0.3,1,3,5,10,15,30,80] в качестве диапазона альфа.
  • Затем повторите подгонку моделей хребта, используя диапазон значений 𝛼α из предыдущего раздела. Сравните результаты.

Теперь о методе RidgeCV. К сожалению, невозможно получить альфа-значения для моделей, которые не были выбраны. Полученные значения ошибок и 𝛼α очень похожи на полученные выше.

The best alpha is: 10.0 with Root Mean Square Error: 32040.433237817062

5.2 Регрессия ЛАССО

LASSO = Оператор наименьшей абсолютной усадки и выбора

Разница между LASSO и Ridge заключается в том, как мы штрафуем функцию стоимости с помощью наших коэффициентов:

Ридж - L2:

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

ЛАССО - L1

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

N.B. штрафы тесно связаны с нормами L1 / L2, которые измеряют длину вектора.

В регрессии LASSO штраф за сложность 𝜆 прямо пропорционален абсолютному значению коэффициентов.

  • Подобно Риджу: эффект компромисса сложности означает, что увеличение лямбда увеличивает смещение, но снижает дисперсию.
  • LASSO с большей вероятностью, чем Ridge, выполнит Выбор характеристик, поскольку для фиксированного 𝜆 LASSO с большей вероятностью приведет к тому, что коэффициенты будут установлены на ноль (поэтому мы выбираем функции за нас)
  • Наказание не такое сильное
  • Медленнее сходится, чем хребет
  • Штраф выборочно уменьшает некоторые коэффициенты
  • Эффект усадки и выделения усиливается по мере увеличения силы регуляризации, поэтому некоторые функции падают до нуля.

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

Функция LassoCV не позволяет установить функцию подсчета очков. Однако созданную выше пользовательскую функцию ошибок (rmse) можно использовать для оценки ошибки в окончательной модели.

Точно так же существует функция эластичной сети с перекрестной проверкой ElasticNetCV, которая представляет собой комбинацию регуляризации L2 и L1.

  • Установите модель Лассо с помощью перекрестной проверки и определите оптимальное значение для 𝛼α и RMSE, используя созданную выше функцию. Обратите внимание, что величина 𝛼α может отличаться от модели Риджа.

Используйте следующие альфы:
[1e-5, 5e-5, 0.0001, 0.0005]

The best alpha is: 0.0005 with Root Mean Square Error: 89886.7232979347

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

print('Of {} coefficients, {} are non-zero with Lasso.'.format(len(lassoCV.coef_), 
                                                               len(lassoCV.coef_.nonzero()[0])))
Output: Of 251 coefficients, 241 are non-zero with Lasso.

5.3 Эластичная сетка (гибридный подход)

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

Валидация может дать нам эмпирический метод выбора между моделями.

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

Гибридный подход

Эластичная сеть - это альтернатива, которая вводит новый параметр 𝛼α, который определяет средневзвешенное значение штрафов L1 и L2. Идея в том, можем ли мы получить лучшее из обоих миров?

Этот новый подход сочетает в себе штрафы от регрессии Ridge и LASSO. Это требует настройки дополнительного параметра, который определяет акцент штрафов L1 и L2 регуляризации:

0.0005 0.1 36220.49757618272

5.4 Сравнение всех моделей

5.5 Резюме поиска по сетке

Резюме для поиска по сетке

Для перекрестной проверки мы использовали два метода:

  • используйте KFolds и вручную создайте цикл для перекрестной проверки
  • используйте cross_val_predict и score, чтобы получить перекрестную оценку в нескольких строках.

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

  • используйте cross_val_predict и score в написанном вручную цикле по гиперпараметрам, затем выберите лучший.

Возможно, неудивительно, что есть функция, которая делает это за нас - GridSearchCV

GridSearchCV(cv=KFold(n_splits=3, random_state=72018, shuffle=True),
             estimator=Pipeline(steps=[('scaler', StandardScaler()),
                                       ('polynomial_features',
                                        PolynomialFeatures()),
                                       ('ridge_regression', Ridge())]),
             param_grid={'polynomial_features__degree': [1, 2, 3],
                         'ridge_regression__alpha': array([ 4.        ,  4.22826702,  4.46956049,  4.7246238 ,  4.99424274,
        5.27924796,  5.58051751,  5.89897953,  6.23561514,  6.59146146,
        6.96761476,  7.36523392,  7.78554391,  8.22983963,  8.69948987,
        9.19594151,  9.72072404, 10.27545421, 10.86184103, 11.48169104,
       12.13691388, 12.82952815, 13.56166768, 14.33558803, 15.15367351,
       16.01844446, 16.93256509, 17.89885162, 18.92028098, 20.        ])})

Мы можем извлечь оценку и лучшие параметры следующим образом

grid.best_score_, grid.best_params_
Output: (0.7862833452665464,
 {'polynomial_features__degree': 1, 'ridge_regression__alpha': 20.0})

Наконец, мы можем сделать прогноз с помощью Grid Search CV, включая данные как в выборке, так и вне выборки.

y_predict = grid.predict(X)
# This includes both in-sample and out-of-sample
r2_score(y, y_predict)
Output: 0.8107931037255625

На этом мы завершаем наш раздел о контролируемом обучении: регресс.

Полный код и блокнот доступны здесь

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

Посетите нашу страницу в Instagram: Путешествие по количеству