Почему gpytorch кажется менее точным, чем scikit-learn? - PullRequest
0 голосов
/ 27 января 2019

Я в данный момент обнаружил gpytorch (https://github.com/cornellius-gp/gpytorch). Похоже, это отличный пакет для интеграции GPR в pytorch. Первые тесты также были положительными. Используя gpytorch, GPU-Power, а также интеллектуальные алгоритмы могут быть использованы для улучшенияпроизводительность по сравнению с другими пакетами, такими как scikit-learn.

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

Для сравнения я взял кодпредоставил пример на официальной странице gpytorch (https://github.com/cornellius-gp/gpytorch/blob/master/examples/03_Multitask_GP_Regression/Multitask_GP_Regression.ipynb) и изменил его в двух частях:

  1. Я использую другое ядро ​​(gpytorch.kernels.MaternKernel (nu = 2.5) вместоgpytorch.kernels.RBFKernel ())
  2. Я использовал другую функцию вывода

Далее я приведу сначала код, используя gpytorch.Впоследствии я предоставляю код для scikit-learn.Наконец, я сравниваю результаты

Импорт (для gpytorch и scikit-learn):

import math
import torch
import numpy as np
import gpytorch

Генерация данных (для gpytorch и scikit-learn):

n = 20
train_x = torch.zeros(pow(n, 2), 2)
for i in range(n):
    for j in range(n):
        # Each coordinate varies from 0 to 1 in n=100 steps
        train_x[i * n + j][0] = float(i) / (n-1)
        train_x[i * n + j][1] = float(j) / (n-1)

train_y_1 = (torch.sin(train_x[:, 0]) + torch.cos(train_x[:, 1]) * (2 * math.pi) + torch.randn_like(train_x[:, 0]).mul(0.01))/4
train_y_2 = torch.sin(train_x[:, 0]) + torch.cos(train_x[:, 1]) * (2 * math.pi) + torch.randn_like(train_x[:, 0]).mul(0.01)

train_y = torch.stack([train_y_1, train_y_2], -1)

test_x = torch.rand((n, len(train_x.shape)))
test_y_1 = (torch.sin(test_x[:, 0]) + torch.cos(test_x[:, 1]) * (2 * math.pi) + torch.randn_like(test_x[:, 0]).mul(0.01))/4
test_y_2 = torch.sin(test_x[:, 0]) + torch.cos(test_x[:, 1]) * (2 * math.pi) + torch.randn_like(test_x[:, 0]).mul(0.01)
test_y = torch.stack([test_y_1, test_y_2], -1)

Теперь дается оценка, как описано в приведенном примере из цитируемой документации:

torch.manual_seed(2) # For a more robust comparison
class MultitaskGPModel(gpytorch.models.ExactGP):
    def __init__(self, train_x, train_y, likelihood):
        super(MultitaskGPModel, self).__init__(train_x, train_y, likelihood)
        self.mean_module = gpytorch.means.MultitaskMean(
            gpytorch.means.ConstantMean(), num_tasks=2
        )
        self.covar_module = gpytorch.kernels.MultitaskKernel(
            gpytorch.kernels.MaternKernel(nu=2.5), num_tasks=2, rank=1
        )

    def forward(self, x):
        mean_x = self.mean_module(x)
        covar_x = self.covar_module(x)
        return gpytorch.distributions.MultitaskMultivariateNormal(mean_x, covar_x)


likelihood = gpytorch.likelihoods.MultitaskGaussianLikelihood(num_tasks=2)
model = MultitaskGPModel(train_x, train_y, likelihood)

# Find optimal model hyperparameters
model.train()
likelihood.train()

# Use the adam optimizer
optimizer = torch.optim.Adam([
    {'params': model.parameters()},  # Includes GaussianLikelihood parameters
], lr=0.1)

# "Loss" for GPs - the marginal log likelihood
mll = gpytorch.mlls.ExactMarginalLogLikelihood(likelihood, model)

n_iter = 50
for i in range(n_iter):
    optimizer.zero_grad()
    output = model(train_x)
    loss = -mll(output, train_y)
    loss.backward()
    # print('Iter %d/%d - Loss: %.3f' % (i + 1, n_iter, loss.item()))
    optimizer.step()

# Set into eval mode
model.eval()
likelihood.eval()

# Make predictions
with torch.no_grad(), gpytorch.settings.fast_pred_var():
    predictions = likelihood(model(test_x))
    mean = predictions.mean
    lower, upper = predictions.confidence_region()

test_results_gpytorch = np.median((test_y - mean) / test_y, axis=0)

Далее я предоставляю код для scikit-learn.Который немного удобнееучить.В последний раз, когда я запускал код, он возвращал:

Переменная 1: scitkit learn является более точным моим фактором: 11.362540360431087

Переменная 2: scitkit learn является более точным моим фактором:29.64760087022618

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

Жду предложений!

Лазло

1 Ответ

0 голосов
/ 27 января 2019

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

В первую очередь это произошло потому, что вы использовали разные модели в sklearn и gpytorch.В частности, по умолчанию sklearn изучает независимых GP в настройке с несколькими выходами (см., Например, обсуждение здесь ).В GPyTorch вы использовали многозадачный метод GP, представленный в Bonilla et al, 2008 .Исправление этой разницы дает:

test_results_gpytorch = [5.207913e-04 -8.469360e-05]

test_results_scitlearn = [3.65288816e-04 4.79017145e-05]

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