Проблема разложения по Холецкому с вычитающим ядром в gpflow - PullRequest
0 голосов
/ 26 января 2020

Я пробую следующее ядро:

class AperiodicMatern12(gpflow.kernels.Kernel):
  def __init__(self, input_dim = None, period = 1.0, variance = 1.0, 
      lengthscales = 1.0, active_dims = None, name = None):
    super().init(input_dim, active_dims = active_dims)
    k0 = gpflow.kernels.Matern12(input_dim, active_dims = active_dims)
    k1 = gpflow.kernels.Matern12(input_dim, active_dims = active_dims)
    k = gpflow.kernels.Periodic(base = k1, period = period)
    self.base = k0
    self.per = k

  @gpflow.params_as_tensors
  def K(self, X, X2 = None):
    res = self.base.K(X, X2) - self.per.K(X, X2)
    return res

  def Kdiag(self, X):
    return np.diag(self.K(X))

Когда я запускаю его с:

lik = gpflow.likelihoods.Gaussian()
k = AperiodicMatern12(1, active_dims = [0])
m = gpflow.models.GPR(X, Y, kern = k)
gpflow.train.ScipyOptimizer().minimize(m)

Я получаю:

InvalidArgumentError (см. выше для отслеживания): разложение Холецкого не было успешным. Ввод может быть недействительным. [[узел GPR-0b2840db-15 / likelihood_1 / Cholesky (определен в /Users/mjg/anaconda3/lib/python3.6/site-packages/gpflow/models/gpr.py:72)]]

Когда я пытаюсь с ядром, определенным как добавка:

@gpflow.params_as_tensors
def K(self, X, X2 = None):
  res = self.base.K(X, X2) + self.per.K(X, X2)
  return res

все работает нормально. X и Y стандартизированы в обоих случаях. Так в чем же проблема с вычитающим ядром?

1 Ответ

1 голос
/ 27 января 2020

Разложение Холецкого работает только для положительно определенных матриц. Таким образом, операция разложения Холецкого не выполняется, если входной аргумент не является положительно определенным, или, что эквивалентно, другими словами, когда входная матрица имеет какие-либо отрицательные собственные значения. Когда это происходит, часто бывает полезно вычислить собственные значения матрицы ядра (например, np.linalg.eigvals(tf.Session().run(k.K(X)))).

Существуют два разных случая, по которым собственные значения матрицы ядра могут быть отрицательными: Наиболее распространенная причина «почти положительные» отрицательные собственные значения из-за проблем с конечной числовой точностью - вот почему мы обычно добавляем матрицу джиттера (диагональная матрица с 10 ^ (- 6) на диагонали) перед вычислением разложения Холецкого в GPflow. Вторая причина заключается в том, что существует ошибка в вычислении матрицы ядра. Это имеет место здесь:

X = np.linspace(0, 10, 11)[:,None]  # dummy 1D data matrix
session = gpflow.get_default_session()
K = session.run(k.K(X))
np.linalg.eigvals(K)

выводит

array([-9.00767547,  1.78835489,  1.51465032,  1.18585391,  0.97478308,
        0.79231475,  0.67625953,  0.5866432 ,  0.52938737,  0.4691057 ,
        0.49032271])

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

ОБНОВЛЕНИЕ: В очень специфических c случаях различие двух ядер может быть другим допустимым положительно определенным ядро. Это относится к конструкции Durrande et al. Для periodi c и aperiodi c ядер класса Matern . Их конструкция специфична c для ядер семейства Matern и отличается от общей реализации ядер periodi c на основе любого стационарного ядра, которое было реализовано в gpflow.kernels.Periodic.

GPflow не предоставляет Durrande et al. / periodi c Ядра Matern из коробки, хотя было бы легко реализовать их поверх GPflow, и проект GPflow был бы рад рассмотреть запрос на извлечение, который добавляет эти ядра в базу кода GPflow.

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