1.7. Гауссовы процессы
Гауссовы процессы (GP) — это непараметрический метод обучения с учителем, используемый для решения задач регрессии и вероятностной классификации.
Преимущества гауссовых процессов:
- Предсказание интерполирует наблюдения (по крайней мере, для стандартных ядер).
- Предсказание является вероятностным (гауссовым), что позволяет вычислять эмпирические доверительные интервалы и на основе этих интервалов определять, нужно ли переобучать (онлайн-обучение, адаптивное обучение) предсказание в некотором регионе интереса.
- Гибкие: можно задавать различные ядра. Предоставляются стандартные ядра, но также можно задавать пользовательские ядра.
Недостатки гауссовых процессов:
- Реализация не является разреженной, т.е. она использует всю информацию о выборке/признаках для выполнения предсказания.
- Она теряет эффективность в многомерных пространствах — особенно когда число признаков превышает несколько десятков.
1.7.1. Регрессия с гауссовыми процессами (GPR)
Класс GaussianProcessRegressor реализует гауссовы процессы (GP) для задач регрессии. Для этого необходимо указать априорное распределение GP. GP объединит это априорное распределение и функцию правдоподобия на основе обучающих выборок. Он позволяет использовать вероятностный подход к предсказанию, предоставляя среднее значение и стандартное отклонение в качестве выходных данных при предсказании.
Предполагается, что среднее значение априорного распределения является постоянным и нулевым (для normalize_y=False) или средним значением обучающих данных (для normalize_y=True). Ковариационная матрица априорного распределения задается с помощью объекта ядра. Гиперпараметры ядра оптимизируются при подгонке к GaussianProcessRegressor путем максимизации логарифмического правдоподобия (LML) на основе переданных optimizer. Поскольку LML может иметь несколько локальных максимумов, оптимизатор можно запускать многократно, задавая n_restarts_optimizer. Первый запуск всегда выполняется, начиная с начальных значений гиперпараметров ядра; последующие запуски выполняются из значений гиперпараметров, выбранных случайным образом из диапазона допустимых значений. Если начальные гиперпараметры должны оставаться фиксированными, можно передать None в качестве оптимизатора.
Уровень шума в целевых значениях может быть задан путем передачи его через параметр alpha, либо глобально как скаляр, либо по каждой точке данных. Обратите внимание, что умеренный уровень шума также может быть полезен для решения проблем с числовой неустойчивостью во время подгонки, поскольку он эффективно реализуется как регуляризация Тихонова, т. е. добавляется к диагонали матрицы ядра. Альтернативой явного указанию уровня шума является включение компоненты WhiteKernel в ядро, которое может оценить глобальный уровень шума из данных (см. пример ниже). На рисунке ниже показано влияние шумных целевых значений, обрабатываемых путем установки параметра alpha.
Реализация основана на алгоритме 2.1 из [RW2006]. Помимо API стандартных оценок scikit-learn, GaussianProcessRegressor:
- позволяет производить предсказания без предварительной подгонки (на основе априорного распределения GP)
- предоставляет дополнительный метод
sample_y(X), который оценивает выборки, полученные из GPR (априорного или апостериорного распределения), на заданных входах - предоставляет метод
log_marginal_likelihood(theta), который может быть использован внешне для других способов выбора гиперпараметров, например, с помощью цепи Маркова Монте-Карло.
Примеры
- Регрессия с гауссовыми процессами: базовый вводный пример
- Возможность регрессии с гауссовыми процессами (GPR) оценивать уровень шума данных
- Сравнение регрессии с ядром Ридджа и регрессии с гауссовым процессом
- Прогнозирование уровня CO2 на наборе данных Mona Loa с использованием регрессии с гауссовым процессом (GPR)
1.7.2. Классификация с гауссовыми процессами (GPC)
Класс GaussianProcessClassifier реализует гауссовы процессы (GP) для задач классификации, точнее, для вероятностной классификации, где предсказания для тестовых данных представляют собой вероятности классов. GaussianProcessClassifier размещает априорное распределение GP на скрытой функции \(f\), которая затем сжимается через функцию связи для получения вероятностной классификации. Скрытая функция \(f\) является так называемой вспомогательной функцией, значения которой не наблюдаются и сами по себе не имеют смысла. Ее цель заключается в удобной формулировке модели, и \(f\) удаляется (интегрируется) во время предсказания. GaussianProcessClassifier реализует логистическую функцию связи, для которой интеграл не может быть вычислен аналитически, но легко аппроксимируется в бинарном случае.
В отличие от задачи регрессии, апостериорное распределение скрытой функции \(f\) не является гауссовым даже для априорного распределения GP, так как гауссова функция правдоподобия не подходит для дискретных меток классов. Вместо этого используется негауссова функция правдоподобия, соответствующая логистической функции связи (логит). GaussianProcessClassifier аппроксимирует не-гауссово апостериорное распределение гауссовым распределением на основе аппроксимации Лапласа. Более подробную информацию можно найти в главе 3 [RW2006].
Предполагается, что среднее значение априорного распределения GP равно нулю. Ковариационная матрица априорного распределения задается с помощью объекта ядра. Гиперпараметры ядра оптимизируются во время подгонки к GaussianProcessRegressor путем максимизации логарифмического правдоподобия (LML) на основе переданных optimizer. Поскольку LML может иметь несколько локальных максимумов, оптимизатор можно запускать многократно, задавая n_restarts_optimizer. Первый запуск всегда выполняется, начиная с начальных значений гиперпараметров ядра; последующие запуски выполняются из значений гиперпараметров, выбранных случайным образом из диапазона допустимых значений. Если начальные гиперпараметры должны оставаться фиксированными, можно передать None в качестве оптимизатора.
GaussianProcessClassifier поддерживает многоклассовую классификацию, выполняя обучение и предсказание либо по принципу один-против-всех, либо один-против-одного. В методе один-против-всех для каждого класса обучается один бинарный классификатор гауссовых процессов, который обучается отделять этот класс от остальных. В методе один-против-одного для каждой пары классов обучается один бинарный классификатор гауссовых процессов, который обучается отделять эти два класса. Предсказания этих бинарных классификаторов объединяются для получения многоклассовых предсказаний. Более подробную информацию см. в разделе о многоклассовой классификации.
В случае классификации с гауссовыми процессами метод «один-против-одного» может быть вычислительно дешевле, так как ему нужно решать много задач, затрагивающих только подмножество всего обучающего набора, а не меньшее число задач на всем наборе данных. Поскольку классификация с гауссовыми процессами имеет кубическую зависимость от размера набора данных, это может быть значительно быстрее. Однако обратите внимание, что «один-против-одного» не поддерживает прогнозирование вероятностей, а только простые предсказания. Кроме того, обратите внимание, что GaussianProcessClassifier (еще) не реализует истинную многоклассовую аппроксимацию Лапласа, а, как обсуждалось выше, основана на решении нескольких задач бинарной классификации внутри, которые объединяются с помощью методов один-против-всех или один-против-одного.
1.7.3. Примеры GPC
1.7.3.1. Вероятностные предсказания с помощью GPC
Этот пример иллюстрирует предсказанную вероятность GPC для ядра RBF с различными значениями гиперпараметров. На первом графике показана предсказанная вероятность GPC с произвольно выбранными гиперпараметрами и с гиперпараметрами, соответствующими максимальному логарифмическому правдоподобию (LML).
Хотя гиперпараметры, выбранные путем оптимизации LML, имеют значительно большее значение LML, они немного хуже работают по показателю логарифмической потери на тестовых данных. На рисунке показано, что это связано с тем, что они демонстрируют резкое изменение вероятностей классов на границах классов (что хорошо), но имеют предсказанные вероятности, близкие к 0,5, далеко от границ классов (что плохо). Этот нежелательный эффект вызван приближением Лапласа, используемым внутри GPC.
На втором графике показано логарифмическое правдоподобие для различных значений гиперпараметров ядра, выделив два выбранных значения гиперпараметров на первом графике черными точками.
1.7.3.2. Иллюстрация GPC на наборе данных XOR
Этот пример иллюстрирует GPC на данных XOR. Сравниваются стационарное изотропное ядро (RBF) и нестационарное ядро (DotProduct). На этом конкретном наборе данных ядро DotProduct получает значительно лучшие результаты, потому что границы классов линейны и совпадают с осями координат. Однако на практике стационарные ядра, такие как RBF, часто дают лучшие результаты.
1.7.3.3. Классификация с помощью гауссовских процессов (GPC) на наборе данных Iris
Этот пример иллюстрирует предсказанную вероятность GPC для изотропного и анизотропного ядра RBF на двумерной версии набора данных Iris. Это иллюстрирует применимость GPC к классификации, не являющейся бинарной. Анизотропное ядро RBF получает немного большее логарифмическое правдоподобие, присваивая разные масштабы длины двум измерениям признаков.
1.7.4. Ядра для гауссовых процессов
Ядра (также называемые «функциями ковариации» в контексте гауссовых процессов) являются ключевым компонентом гауссовых процессов, определяющим форму априорного и апостериорного распределений гауссова процесса. Они кодируют предположения о функции, которую необходимо обучить, определяя «подобие» двух точек данных в сочетании с предположением, что похожие точки данных должны иметь похожие целевые значения. Можно выделить две категории ядер: стационарные ядра зависят только от расстояния между двумя точками данных, а не от их абсолютных значений \(k(x_i, x_j)= k(d(x_i, x_j))\) и, следовательно, инвариантны к сдвигам в пространстве входных данных, в то время как нестационарные ядра также зависят от конкретных значений точек данных. Стационарные ядра можно далее разделить на изотропные и анизотропные ядра, где изотропные ядра также инвариантны к поворотам в пространстве входных данных. Более подробную информацию можно найти в главе 4 [RW2006]. Для получения руководства по оптимальному сочетанию различных ядер см. [Duv2014].
API ядер гауссовых процессов
Основное применение Kernel заключается в вычислении ковариации гауссова процесса между точками данных. Для этого можно вызвать метод __call__ ядра. Этот метод может использоваться для вычисления «автоковариации» всех пар точек данных в 2D-массиве X или «взаимоковариации» всех комбинаций точек данных 2D-массива X с точками данных в 2D-массиве Y. Для всех ядер k (за исключением WhiteKernel) справедливо следующее тождество: k(X) == K(X, Y=X)
Если используется только диагональ автоковариации, можно вызвать метод diag() ядра, что более эффективно, чем эквивалентный вызов __call__: np.diag(k(X, X)) == k.diag(X)
Ядра параметризуются вектором \(\theta\) гиперпараметров. Эти гиперпараметры могут, например, управлять масштабами или периодичностью ядра (см. ниже). Все ядра поддерживают вычисление аналитических градиентов автоковариации ядра по \(log(\theta)\) с помощью установки eval_gradient=True в методе __call__. То есть возвращается массив (len(X), len(X), len(theta)), где элемент [i, j, l] содержит \(\frac{\partial k_\theta(x_i, x_j)}{\partial log(\theta_l)}\). Этот градиент используется гауссовым процессом (как регрессором, так и классификатором) для вычисления градиента логарифмической правдоподобия, который, в свою очередь, используется для определения значения \(\theta\), максимизирующего логарифмическую правдоподобие, с помощью градиентного восхождения. Для каждого гиперпараметра необходимо указать начальное значение и границы при создании экземпляра ядра. Текущее значение \(\theta\) можно получить и установить с помощью свойства theta объекта ядра. Кроме того, границы гиперпараметров можно получить с помощью свойства bounds ядра. Обратите внимание, что оба свойства (theta и bounds) возвращают логарифмически преобразованные значения используемых внутренне значений, поскольку они обычно более подходят для оптимизации с использованием градиента. Спецификация каждого гиперпараметра хранится в виде экземпляра Hyperparameter в соответствующем ядре. Обратите внимание, что ядро, использующее гиперпараметр с именем «x», должно иметь атрибуты self.x и self.x_bounds.
Абстрактный базовый класс для всех ядер — Kernel. Ядро реализует интерфейс, аналогичный интерфейсу BaseEstimator, предоставляя методы get_params(), set_params(), и clone() . Это позволяет устанавливать значения ядер также с помощью мета-эстиматоров, таких как Pipeline или GridSearchCV. Обратите внимание, что из-за вложенной структуры ядер (путем применения операторов ядер, см. ниже) имена параметров ядер могут стать относительно сложными. В общем случае для бинарного оператора ядер параметры левого операнда имеют префикс k1__, а параметры правого операнда — префикс k2__ . Дополнительный удобный метод — clone_with_theta(theta), который возвращает клонированную версию ядра, но с гиперпараметрами, установленными в theta. Пример:
>>> from sklearn.gaussian_process.kernels import ConstantKernel, RBF
>>> kernel = ConstantKernel(constant_value=1.0, constant_value_bounds=(0.0, 10.0)) * RBF(length_scale=0.5, length_scale_bounds=(0.0, 10.0)) + RBF(length_scale=2.0, length_scale_bounds=(0.0, 10.0))
>>> for hyperparameter in kernel.hyperparameters: print(hyperparameter)
Hyperparameter(name='k1__k1__constant_value', value_type='numeric', bounds=array([[ 0., 10.]]), n_elements=1, fixed=False)
Hyperparameter(name='k1__k2__length_scale', value_type='numeric', bounds=array([[ 0., 10.]]), n_elements=1, fixed=False)
Hyperparameter(name='k2__length_scale', value_type='numeric', bounds=array([[ 0., 10.]]), n_elements=1, fixed=False)
>>> params = kernel.get_params()
>>> for key in sorted(params): print("%s : %s" % (key, params[key]))
k1 : 1**2 * RBF(length_scale=0.5)
k1__k1 : 1**2
k1__k1__constant_value : 1.0
k1__k1__constant_value_bounds : (0.0, 10.0)
k1__k2 : RBF(length_scale=0.5)
k1__k2__length_scale : 0.5
k1__k2__length_scale_bounds : (0.0, 10.0)
k2 : RBF(length_scale=2)
k2__length_scale : 2.0
k2__length_scale_bounds : (0.0, 10.0)
>>> print(kernel.theta) # Note: log-transformed
[ 0. -0.69314718 0.69314718]
>>> print(kernel.bounds) # Note: log-transformed
[[ -inf 2.30258509]
[ -inf 2.30258509]
[ -inf 2.30258509]]
Все ядра гауссовых процессов совместимы с sklearn.metrics.pairwise и наоборот: экземпляры подклассов Kernel могут передаваться как metric в pairwise_kernels из sklearn.metrics.pairwise. Кроме того, функции ядер из pairwise можно использовать в качестве ядер GP, используя класс-обертку PairwiseKernel. Единственное замечание состоит в том, что градиент гиперпараметров не является аналитическим, а численным, и все эти ядра поддерживают только изотропные расстояния. Параметр gamma рассматривается как гиперпараметр и может быть оптимизирован. Другие параметры ядра устанавливаются непосредственно при инициализации и остаются неизменными.
1.7.4.1. Базовые ядра
Ядро ConstantKernel может использоваться в составе ядра Product, где оно масштабирует величину другого фактора (ядра), или в составе ядра Sum, где оно изменяет среднее значение гауссова процесса. Оно зависит от параметра \(constant\_value\). Оно определяется как:
Основное использование ядра WhiteKernel — как части суммы ядер, где оно объясняет шумовую составляющую сигнала. Настройка его параметра \(noise\_level\) соответствует оценке уровня шума. Оно определяется как:
1.7.4.2. Операторы ядер
Операторы ядер берут одно или два базовых ядра и объединяют их в новое ядро. Ядро Sum берет два ядра \(k_1\) и \(k_2\) и объединяет их через \(k_{sum}(X, Y) = k_1(X, Y) + k_2(X, Y)\). Ядро Product берет два ядра \(k_1\) и \(k_2\) и объединяет их через \(k_{product}(X, Y) = k_1(X, Y) * k_2(X, Y)\). Ядро Exponentiation берет одно базовое ядро и скалярный параметр \(p\) и объединяет их через \(k_{exp}(X, Y) = k(X, Y)^p\). Обратите внимание, что магические методы __add__, __mul___ и __pow__ переопределены для объектов ядра, поэтому можно использовать, например, RBF() + RBF() в качестве сокращения для Sum(RBF(), RBF()).
1.7.4.3. Ядро радиальной базисной функции (RBF)
Ядро RBF является стационарным ядром. Оно также известно как ядро «квадратного экспоненциального» типа. Оно параметризуется параметром масштаба длины \(l>0\), который может быть либо скаляром (изотропный вариант ядра), либо вектором с тем же числом измерений, что и входные данные \(x\) (анизотропный вариант ядра). Ядро определяется следующим образом:
где \(d(\cdot, \cdot)\) — евклидово расстояние. Это ядро бесконечно дифференцируемо, что подразумевает, что GP с этим ядром в качестве функции ковариации имеет среднеквадратичные производные всех порядков и, следовательно, является очень гладким. Предварительное и апостериорное распределение GP, полученное с помощью ядра RBF, показаны на следующем рисунке:
1.7.4.4. Ядро Матерна
Ядро Matern является стационарным ядром и обобщением ядра RBF. Оно имеет дополнительный параметр \(\nu\), который управляет гладкостью полученной функции. Оно параметризуется параметром масштаба длины \(l>0\), который может быть либо скаляром (изотропный вариант ядра), либо вектором с тем же числом измерений, что и входные данные \(x\) (анизотропный вариант ядра).
Математическая реализация ядра Матерна
Ядро определяется следующим образом:
где \(d(\cdot,\cdot)\) — евклидово расстояние, \(K_\nu(\cdot)\) — модифицированная функция Бесселя, а \(\Gamma(\cdot)\) — гамма-функция. При \(\nu\rightarrow\infty\) ядро Матерна сходится к ядру RBF. Когда \(\nu = 1/2\), ядро Матерна становится идентичным ядру абсолютной экспоненты, т. е.
В частности, \(\nu = 3/2\):
и \(\nu = 5/2\):
являются популярными вариантами для обучения функций, которые не являются бесконечно дифференцируемыми (как предполагается ядром RBF), но по крайней мере один раз (\(\nu = 3/2\)) или дважды дифференцируемыми (\(\nu = 5/2\)).
Гибкость управления гладкостью обучаемой функции с помощью \(\nu\) позволяет адаптироваться к свойствам истинного функционального соотношения.
Предварительное и апостериорное распределение GP, полученное с помощью ядра Матерна, показаны на следующем рисунке:
См. [RW2006], стр.84, для получения дополнительной информации о различных вариантах ядра Матерна.
1.7.4.5. Ядро рациональной квадратичной функции
Ядро RationalQuadratic может быть представлено как смесь масштабов (бесконечная сумма) ядер RBF с различными характеристическими масштабами длины. Оно параметризуется параметром масштаба длины \(l>0\) и параметром смеси масштабов \(\alpha>0\). В настоящее время поддерживается только изотропный вариант, где \(l\) — скаляр. Ядро определяется следующим образом:
Предварительное и апостериорное распределение GP, полученное с помощью ядра RationalQuadratic, показаны на следующем рисунке:
1.7.4.6. Ядро Exp-Sine-Squared
Ядро ExpSineSquared позволяет моделировать периодические функции. Оно параметризуется параметром масштаба длины \(l>0\) и параметром периодичности \(p>0\). В настоящее время поддерживается только изотропный вариант, где \(l\) — скаляр. Ядро определяется следующим образом:
Предварительное и апостериорное распределение GP, полученное с помощью ядра ExpSineSquared, показаны на следующем рисунке:
1.7.4.7. Ядро скалярного произведения
Ядро DotProduct является нестационарным и может быть получено из линейной регрессии, задавая \(N(0, 1)\) на коэффициенты \(x_d (d = 1, . . . , D)\) и \(N(0, \sigma_0^2)\) на смещение. Ядро DotProduct инвариантно к повороту координат вокруг начала координат, но не к сдвигам. Оно параметризуется параметром \(\sigma_0^2\). При \(\sigma_0^2 = 0\) ядро называется однородным линейным ядром, в противном случае — неоднородным. Ядро определяется следующим образом
Ядро DotProduct обычно комбинируется с возведением в степень. Пример с показателем 2 показан на следующем рисунке:
1.7.4.8. Ссылки
© 2007–2025 The scikit-learn developers
Licensed under the 3-clause BSD License.
https://scikit-learn.org/1.6/modules/gaussian_process.html