Как сделать кросс валидацию python

Добавил пользователь Cypher
Обновлено: 04.10.2024

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

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

Три шага, вовлеченные в перекрестную проверку, следующие:

  1. Зарезервируйте некоторую часть выборочного набора данных.
  2. Используя остальные данные, обучаем модель.
  3. Протестируйте модель, используя резервную часть набора данных.

Методы перекрестной проверки

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

K-Fold Cross Validation
В этом методе мы разделяем набор данных на k подмножеств (известных как сгибы), затем выполняем обучение на всех подмножествах, но оставляем одно (k-1) подмножество для оценки обученной модели. В этом методе мы повторяем k раз с другим подмножеством, зарезервированным для целей тестирования каждый раз.

пример
На диаграмме ниже показан пример обучающих подмножеств и оценочных подмножеств, сгенерированных в k-кратной перекрестной проверке. Здесь у нас всего 25 экземпляров. В первой итерации мы используем первые 20 процентов данных для оценки, а оставшиеся 80 процентов для обучения (4 тестирование и 25 обучение), в то время как во второй итерации мы используем второе подмножество 20 процентов для оценка и оставшиеся три подмножества данных для обучения (7 тестирование и [1-5 и 10-25] обучение) и так далее.


Сравнение разделения поезда / теста с перекрестной проверкой

Преимущества разделения поезда / теста:

  1. Это выполняется в K раз быстрее, чем перекрестная проверка Leave One Out, потому что перекрестная проверка с K-кратным повторением повторяет разделение поезд / тест K-раз.
  2. Проще изучить подробные результаты процесса тестирования.

Преимущества перекрестной проверки:

Код Python для перекрестной проверки k-кратной проверки.

Линейная регрессия, регуляризация, кросс-валидация и Grid Search в PySpark

Линейная регрессия, регуляризация, кросс-валидация и Grid Search в PySpark

Линейная регрессия, регуляризация, кросс-валидация и Grid Search в PySpark

Автор Роман Котюбеев Категория Machine Learning, Spark, Статьи

В прошлый раз мы говорили о решении задачи классификации в рамках Machine Learning с помощью PySpark MLlib. Сегодня рассмотрим задачу регрессии. Читайте далее: что такое линейная регрессия, L1 и L2 регуляризация, алгоритм подбора значений гиперпараметров Grid Search, а также применение кросс-валидации в PySpark.

Датасет с домами на продажу

Обучать модель машинного обучения (Machine Learning) будем на датасете с домами на продажу в округе Кинг (Вашингтон, США). Его можно скачать напрямую с Kaggle или воспользоваться Kaggle API, как мы описывали здесь. Датасет содержит такие атрибуты, как цена, количество комнат, количество ванных комнат, дату постройки, площадь на квадратный фут (1 фут = 0.3 метра) и другие. Код на Python для инициализации Spark-приложения и создания DataFrame выглядит следующим образом:

Векторизация и разделение выборки на обучающую и тестовую

Как мы уже говорили в предыдущей статье, алгоритмы Machine Learning в PySpark принимают на вход только вектора, поэтому нам необходимо предварительно векторизовать данные.

Мы будем обучать модель на 5 признаках: площадь на квадратный фут, количество комнат, количество ванных комнат и дата постройки. Отберем их с помощью метода select :

А чтобы векторизовать выбранные признаки, воспользуемся классом VectorAssembler. Он принимает в качестве аргументов список признаков, которые необходимо преобразовать в вектор, и название преобразованного вектора. Вот так это выглядит в Python:

Теперь разобьём выборку на обучающую и тестовую. На обучающей создадим модель Machine Learning, а на тестовой проверим эффективность этой модели. Причём, разделим данные в пропорции 9:1. Python-код:

Grid Search: оптимизация гиперпараметров

Одна из задач машинного обучения является подбор гиперпараметров, которые задает Data Scientist перед обучением. У каждого алгоритма Machine Learning они свои. Однако подбирать их вручную утомительно и затратно, поэтому существуют специальные алгоритмы подбора. В PySpark встроен один из таких алгоритмов – Grid Search.

Grid search есть не что иное, как комбинация из всех значений заданных гиперпараметров. Например, пусть имеется два гиперпараметра: первый может принимать 2 значения, а второй – 3. Тогда возможно всего 6 комбинаций:

Гиперпараметры линейной регрессии в PySpark

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

Эти параметры задают вид регуляризации: L1 или L2. Единственное, что делает регуляризация — это добавляет ещё один параметр к целевой функции, а обучение остаётся тем же самым. Как известно, цель машинного обучения минимизировать целевую функцию. В линейной регрессии целевая функция — это сумма квадратов остатков [1]. Она определяется как:

В L1-регуляризации к целевой функции добавляется сумма весов, и такая регуляризация называется Lasso. Выражается она так:

В L2-регуляризации к целевой функции добавляется сумма квадратов весов, и такая регуляризация называется Ridge. Выражается она так:

Кроме того, эти два вида регуляризации можно соединить вместе, и такая регуляризация называется Elastic Net.

В линейной регрессии без регуляризации предполагается, что коэффициенты регрессии (веса) могут равновероятно принимать любые значения. В L1 регуляризации предполагается, что эти коэффициенты распределены по закону Лапласа, в L2 — по закону Гаусса. И та, и другая регуляризация не даёт весам быть слишком большими, и, возможно, повысится обобщающая способность модели.

Обобщенная формула для регуляризации в PySpark

В Python-библиотеке Scikit-learn все виды регуляризации линейной регрессии разделены по соответствующим классам Lasso, Ridge и ElasticNet. Но в PySpark это реализовано в общем виде и зависит от гиперпарметров regParam и elasticNetParam. Выражается это так:

Таким образом, задавая определённые значения regParam и elasticNetParam, можно получить следующие результаты:

regParam = 0 – это линейная регрессия без регуляризации;

regParam > 0, elasticNetParam = 0 ведет к L2-регуляризация (Ridge);

regParam > 0, elasticNetParam = 1 ведет к L1-регуляризация (Lasso);

regParam > 0, 0 addGrid добавляются гиперпарметр и значения, которые он может принимать. Выберем 3 значения для regParam и два значения для elasticNetParam. Так это выглядит в Python:

Метрика качества

Нам также нужно указать метрику качества для оценки модели. Для задачи регрессии используется RegressionEvaluator, который по умолчанию в качестве метрики использует среднюю квадратическую ошибку (MSE). MSE можно поменять на среднюю абсолютную ошибку (MAE). Кроме того, мы должны указать названия целевого и предсказанного атрибутов. Линейная регрессия в PySpark после обучения создает предсказанный атрибут под название prediction, а целевая так и остаётся price. Python-код выглядит так:

Кросс-валидация

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

Кросс-валидация PySpark

В PySpark кросс-валидация реализуется через CrossValidator. В нем нам нужно указать три аргумента:

estimator — модель Machine Learning, в нашем случае линейная регрессия;

estimatorParamMaps — алгоритм оптимизации гиперпараметров, в нашем случае Grid Search;

evaluator — метрика качества, в нашем случае RegressionEvaluator.

Также можно указать в аргументах numFolds — количество блоков N (по умолчанию их 3). После указания значений этих аргументов вызывается метод fit для выполнения кросс-валидации. В Python это выглядит следующим образом:

Результаты кросс-валидации

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

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

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

Как видим, лучшая модель имеет гиперпараметр elasticNetParam равный 1, а regParam – 0.1. Значения этих параметров показывают, что лучшая модель использует L1-регуляризацию (regParam > 0, elasticNetParam=1).

Больше подробностей о линейной регрессии, L1 и L2 регуляризации, алгоритмах подбора гиперпараметрах, а также о кросс-валидации в PySpark на примерах задач Data Science и Big Data вы узнаете на наших практических курсах по Apache Spark и Machine Learning в лицензированном учебном центре обучения и повышения квалификации разработчиков, менеджеров, архитекторов, инженеров, администраторов, Data Scientist’ов и аналитиков Big Data в Москве:

DS_Deep_2.4_Site-5020-1a325c.jpg

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

При выполнении кросс-валидации на временных рядах нужно понимать, что данные зависят друг от друга, то есть их последовательность важна. Если в обычных данных мы могли взять выборки произвольно (случайным образом) и сформировать из них Train-Test, то в случае временного ряда так делать уже нельзя.

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

Содержание

Пусть [math] X [/math] — множество признаков, описывающих объекты, а [math] Y [/math] — конечное множество меток.

[math]T^l = <(x_i, y_i)>_^, x_i \in X, y_i \in Y[/math] — обучающая выборка,

[math]Q[/math] — мера качества,

[math]\mu: (X \times Y)^l \to A, [/math] — алгоритм обучения.

Обучающая выборка один раз случайным образом разбивается на две части [math] T^l = T^t \cup T^ [/math]

Hold-out.jpg


После чего решается задача оптимизации:

[math]HO(\mu, T^t, T^) = Q(\mu(T^t), T^) \to min [/math] ,

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

  1. Выбирается значение [math]t[/math] ;
  2. Выборка разбивается всеми возможными способами на две части [math] T^l = T^t \cup T^ [/math] .

CompleteCrossValidation.jpg

Здесь число разбиений [math]C_l^[/math] становится слишком большим даже при сравнительно малых значениях t, что затрудняет практическое применение данного метода.

  1. Обучающая выборка разбивается на [math] k [/math] непересекающихся одинаковых по объему частей;
  2. Производится [math] k [/math] итераций. На каждой итерации происходит следующее:
    1. Модель обучается на [math] k - 1 [/math] части обучающей выборки;
    2. Модель тестируется на части обучающей выборки, которая не участвовала в обучении.

    Каждая из [math]k[/math] частей единожды используется для тестирования. Как правило, [math]k = 10[/math] (5 в случае малого размера выборки).

    K-fold-validation.jpg

    [math]T^l = F_1 \cup \dots \cup F_k, |F_i| \approx \frac, \\ CV_k = \frac \sum_^ Q(\mu(T^l \setminus F_i),F_i) \to min [/math] .

    1. Процедура выполняется [math]t[/math] раз:
      1. Обучающая выборка случайным образом разбивается на [math]k[/math] непересекающихся одинаковых по объему частей;
      2. Производится [math] k [/math] итераций. На каждой итерации происходит следующее:
        1. Модель обучается на [math] k - 1 [/math] части обучающей выборки;
        2. Модель тестируется на части обучающей выборки, которая не участвовала в обучении.


        [math]T^l = F_ \cup \dots \cup F_ = \dots = F_ \cup \dots \cup F_, |F_| \approx \frac [/math] ,

        Выборка разбивается на [math]l-1[/math] и 1 объект [math]l[/math] раз.

        LeaveOneOut.jpg

        [math]LOO = \frac \sum_^ Q(\mu(T^l \setminus p_i),p_i) \to min [/math] , где [math]p_i = (x_i, y_i)[/math] .

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

        Недостатком LOO является большая ресурсоёмкость, так как обучаться приходится [math]L[/math] раз. Некоторые методы обучения позволяют достаточно быстро перенастраивать внутренние параметры алгоритма при замене одного обучающего объекта другим. В этих случаях вычисление LOO удаётся заметно ускорить.

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

        CompleteCrossValidation.jpg

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

        Читайте также: