Гиперпараметры - это параметры в схеме обучения любого алгоритма предсказания. Сама по себе схема в общем случае выглядит следующим образом:
- На вход алгоритма обучения модели
$a$ мы подаём гиперпараметры, которые задают поведение алгоритма, и набор данных$X$ . -
$a$ возвращает некие параметры$\delta$ . - Далее, на вход алгоритма предсказания
$a_{\delta}$ мы подаём$\delta$ и объект$x$ . -
$a_{\delta}$ возвращает некое предсказание$y$ .
Исходя из этого, гиперпараметры - это:
- параметры алгоритма обучения;
- параметры, которые не меняются во время обучения;
- параметры, которые можно установить до наблюдения набора данных;
- структурные параметры.
На самом деле, для нахождения гиперпараметров (как части данных) можно также установить задачу оптимизации как и в случае с
-
$\mathcal{D}$ - набор данных; -
$A$ - алгоритм обучения; -
$p$ - гиперпараметры алгоритма обучения; -
$\mathcal{L}$ - функция ошибки (валидация);
Тогда нашей задачей оптимизации будет нахождение
Поиск нужных гиперпараметров мы можем рассматривать как часть обучения. Будем считать, что у нас есть множество гиперпараметров
- Будем перебирать гиперпараметры
$p_i$ и запускать алгоритм обучения модели$a$ на$p_i$ и$X_{\mathtt{train}}$ . -
$a$ возвращает некие параметры модели$\delta_i$ . - Далее, на вход алгоритма предсказания
$a_{\delta}$ мы подаём$\delta_i$ и объект из$X_{\mathtt{valid}}$ . -
$a_{\delta}$ возвращает некое предсказание$y$ . -
$y$ подаём в функцию ошибки (валидации) и на основе его значения либо запомним$p_i$ , либо сможем выбрать более оптимальные, лучшие параметры$p_j$ . - Наконец,
$p_{\text{best}}$ вместе с набором данных$X$ подаём в алгоритм обучения модели$a$ и получаем финальные параметры модели$\delta_{\text{best}}$ .
Точно такую же задачу можно задать на выборе алгоритма
А если хотим совместить? С одной стороны, мы могли бы выбирать алгоритм настройкой гиперпараметров, тогда:
- Рассмотрим несколько алгоритмов обучения
$A^1, ~ A^2, ~ \ldots$ - с соответствующими списками гиперпараметров
${p^1_1, ~ p^1_2, ~ \ldots}$ ,${p^2_1, ~ p^2_2, ~ \ldots}$ ,$\ldots$
Мы бы построили универсальный алгоритм
С другой же, мы могли бы получить набор гиперпараметров выбором алгоритма, тогда:
- Специализируем алгоритмы
$A^1, ~ A^2, ~ \ldots$ соответствующими гиперпараметрами${p^1_1, ~ p^1_2, ~ \ldots}$ ,${p^2_1, ~ p^2_2, ~ \ldots}$ ,$\ldots$ - Получим список алгоритмов для выбора
$A^1_1, ~ A^1_2, ~ \ldots, A^2_1, ~ A^2_2, ~ \ldots$
В таком случае мы получаем большое количество алгоритмов, каждый из которых необходимо запустить на одних и тех же наборах данных. Поэтому обычно мы интерпретируем гиперпараметры как признаки - либо число, либо категория, тогда мы относим категориальные параметры к "алгоритмам", а числовые - к "гиперпараметрам". Получаем по итогу много меньше сущностей, на которых нужно запустить набор данных
Есть два основных подхода к конфигурации: линейный подход (pipeline) и древовидный подход:
- Линейный подход. Мы задаём линейный конвейер обработки набора данных
$X$ с помощью разных алгоритмов и гиперпараметров для получения конкретных параметров, которые затем используются в следующем алгоритме и гиперпараметрах, чтобы получить следующие параметры модели. - Древовидный подход. Мы делим каждую сущность (будь то алгоритм или гиперпараметры) на дерево с вершинами: вершина ИЛИ - выбирается один из
$n$ , вершина И выбираются все, и Лист - обычно, это неделимые данные.
Самый простейший метод получения оптимального набора гиперпаметров. Мы выписываем значения всех гиперпараметров, все числовые дискретизируем, а затем мы перебираем все возможные комбинации значений, которые образуют декартово произведение списков значений гиперпараметров (сетку).
Грубо говоря, полный перебор вариантов. Мы можем оптимизировать потребляемую память, получая значения "на лету" (например, простейшие преобразования).
Какие проблемы? Очевидно, что такой подход требует слишком много времени: для
Тем не менее, такой подход используется и легко позволяет проанализировать число запусков алгоритма в древовидном подходе к конфигурации, где вершина ИЛИ - это общее количество параметров (сумма), вершина И - это количество комбинаций (произведение).
Работает почти также как поиск по сетке, но с двумя важными ньюансами: значения гиперпараметров задаются случайными распределениями (на каждой итерации комбинация значений гиперпараметров выбирается случайно) и число итераций обычно ограничивается лимитом вычислений (или общим временем исполнения).
В чём есть преимущества? В отличии от сетки, мы не берем какой-то шаг выбора параметров для гиперпараметров, а значит у нас появляется больший шанс выбрать, например, тот вариант, который будет лучший, но лежит между двумя значениями сетки параметров. Может работать с гиперпараметрами у которых бесконечное число значений (так как мы выберем какое-то множество из
В чём проблемы? Если у нас есть категориальные параметры, то, из-за случайного выбора, может получиться так, что некоторые комбинации с категориями могут повторяться, а некоторые могут быть вообще не рассмотрены. Например, для получения всех
Есть ещё одно важное замечание по поводу случайного выбора - это распределение для случайного поиска. Равномерное распределение - это тот, который возникает при распространении идеи "равновозможности исходов" на непрерывный случай, то есть каждый из исходов имеет равный шанс на исполнение. Такое распределение мы можем симулировать с помощью дополнительной сетки для случайного поиска, которая будет отвечать true
, если такая точка была, иначе false
, и в зависимости от ответа, будет браться некоторый сдвиг относительно этой точки в какую-ту сторону.
Как же выбрать распределение? Существует следующие рекомендательные виды при трёх случаях:
- Неограниченное: нормальное распределение.
- Ограниченное с одной стороны: экспоненциальное или логнормальное распределение.
- Ограниченное с двух сторон: равномерное или бета-распределение.
Иногда виды распределений смешивают, чтобы получить более "честный" результат выбора. Например, если на некотором отрезке встречаются значения из интервала
Здесь под чёрным ящиком мы понимаем алгоритм, про который мы ничего кроме его выходного значения на входное значения не знаем. Как правило, применяется для недифференцируемых, невыпуклых или медленно вычислимых функций. Критерием остановки работы алгоритма служат следующие ограничения:
- Если выходное значение функции
$\mathcal{L}$ достиг желаемого минимума при некотором фиксированном времени (грубо говоря,$\varepsilon$ ). - Если количество вызовов функции
$\mathcal{L}$ достиг максимального количества вызовов (грубо говоря, количество итераций).
В Black-Box у нас бывают задачи решения оптимизации абстрактных и числовых объектов.
При оптимизации абстрактных объектов помимо функции ошибок
-
Генерация - создаёт новый объект
$$ \mathtt{rand}() ~ : ~ X $$
-
Мутация - создаёт из объекта
$x$ новый объект$x'$ , который похож на$x$ $$ \mathtt{mutate}(x) ~ : ~ X \to X $$
-
Кроссовер - создаёт из двух объектов третий, который одновременно похож на первый и второй
$$ \mathtt{cross}(x_1, ~ x_2) ~ : ~ X \times X \to X $$
При оптимизации в числовом пространстве мы считаем
Существуют также многокритериальные алгоритмы, в которых обычно используется две и больше функций ошибок. Например, сама по себе ошибка решения и время работы алгоритма при таком параметре. При таком подходе нам необходимо смотреть на величины с разных сторон, их нельзя просто так суммировать (может быть слишком маленькое время работы, но слишком большая ошибка, и наоборот). Итого мы образуем некоторое пространство решений, где есть так называемые плохие решения - это те, для которых не существует решения при других параметрах лучше него, и парето-фронт решений - множество оптимальных решений.
Здесь мы используем так называемую суррогатную функцию
Ещё данную оптимизацию называют частным случаем обучения с подкреплением. Здесь нам нужны алгоритмы машинного обучению для аппроксимации, так как там вектор гиперпараметров становится вектором признаков для обучения.
Обычно, в машинном обучении, мы стараемся работать с векторами (пакетами) чисел: категории мы приводим к One-Hot кодированию (битовый вектор) и обрабатываем по своему, числовые значения оставляем как есть. Обычно, мы подаём алгоритму функцию ошибки и не задумываемся, и казалось бы, мы также могли бы сделать при смешивании двух видов значений, но это не так:
-
В одном случае функция ошибки берёт
$x \in \mathbb{R}$ и возвращает ошибку$$ \mathcal{L}(\mathbb{R}^m) \to \mathtt{Err} $$
-
В другом же - мы берём на вход гиперпараметры и возвращаем ошибку
$$ \mathcal{L}(P) \to \mathtt{Err} $$
А если мы хотим иметь гиперпараметры, в которых встречаются числовые параметры, то нам нужна промежуточная функция преобразования
-
Пусть числа - это и есть целочисленные значения, тогда
$$ \begin{aligned} 0.1 \rightarrowtail 0 \to \mathtt{Err}1 \ 0.2 \rightarrowtail 0 \to \mathtt{Err}{\underline{\mathbf{1}}} \end{aligned} $$
То есть, мы хоть и изменили значение, но алгоритм считает, что ничего не изменилось.
-
Тоже самое происходит и с категориями. Мы сделали One-Hot кодирование, а затем вернули категориальные значения с помощью
$\argmax$ , тогда$$ \begin{aligned} [0.1, ~ 7, ~ -3] \rightarrowtail 2 \to \mathtt{Err}_1 \ [0.1, ~ 6, ~ -3] \rightarrowtail 2 \to \mathtt{Err}1 \ [0.1, ~ 7, ~ 6] \rightarrowtail 2 \to \mathtt{Err}{\underline{\mathbf{1}}} \end{aligned} $$
Казалось бы, на третьей итерации у нас произошли сильные изменения в отличия от первой и должна была быть другая ошибка, но из-за
$\argmax$ - ровно та же.
Таким образом, для таких алгоритм лучше всегда использовать покоординатные преобразования с помощью операторов преобразований: например, при мутации категории её значение заменяется на случайное другое, при мутации целого числа к нему прибавляется целочисленный сдвиг и тому подобное.
Тоже самое касается линейной конфигурации. Возьмем модель SVM и приведем гиперпараметры:
- если выбрано ядро
$\mathtt{poly}$ , то от изменения$\gamma$ функция ошибки не изменится. Аналогично с ядром$\mathtt{gauss}$ и гиперпараметром$d$ - если модифицируются сразу все числовые гиперпараметры, то изменение одного из них может ухудшить гиперпараметр для одного ядра и улучшить для другого, но целевая функция будет вычислена только для текущего выбранного ядра.