GPflow - классификация GP с 1-мерным линейным ядром плохо подходит для двумерных данных - PullRequest
0 голосов
/ 21 апреля 2020

После выпуска # 1435 у меня возник дополнительный вопрос о том, как использовать GPflow.

Я повторяю проблему в дополнительном ядре: https://github.com/avalonhse/BayesNotebook/blob/master/Issue_2_GPFlow_Linear_Classification.ipynb

Моя цель - подгонка аддитивного ядра к двумерным данным (квадратная экспонента в измерении 1 и линейное ядро ​​в измерении 2). Следуя инструкции # 1435 , я успешно подгонял модель к ядру gpflow.kernels.Linear (дисперсия = 0,1).

Линейное ядро ​​

Однако, когда я использую ядро ​​gpflow.kernels.Linear (active_dims = 1 , дисперсия = 0,01), как я изначально планировал, модель не подходит. Я использовал GPy с тем же ядром в качестве ссылки, тогда результат выглядит разумным.

1-dim GPFlow kernel

import numpy as np
X = np.array([[ 9.96578428, 60.],[ 9.96578428, 40.],[ 9.96578428, 20.],
       [10.96578428, 30.],[11.96578428, 40.],[12.96578428, 50.],
       [12.96578428, 70.],[8.96578428, 30. ],[ 7.96578428, 40.],
       [ 6.96578428, 50.],[ 6.96578428, 30.],[ 6.96578428, 10.],
       [11.4655664 , 71.],[ 8.56605404, 63.],[12.41574177, 69.],
       [10.61562964, 48.],[ 7.61470984, 51.],[ 9.31514956, 45.]])
Y = np.array([[1., 1., 0., 0., 0., 0., 0., 0., 0., 1., 1., 0., 1., 1., 0., 0., 1., 0.]]).T

# plotting
import matplotlib.pyplot as plt
import matplotlib
%matplotlib inline
def plot(X,Y):
    mask = Y[:, 0] == 1

    plt.figure(figsize=(6, 6))
    plt.plot(X[mask, 0], X[mask, 1], "oC0", mew=0, alpha=0.5)

    plt.ylim(-10, 100)
    plt.xlim(5, 15)

    _ = plt.plot(X[np.logical_not(mask), 0], X[np.logical_not(mask), 1], "oC1", mew=0, alpha=0.5)

plot(X,Y)

# Evaluate real function and the predicted probability
res = 500
xx, yy = np.meshgrid(np.linspace(5, 15, res),
                     np.linspace(- 10, 120, res))
Xplot =  np.vstack((xx.flatten(), yy.flatten())).T

# Code followed the Notebook : https://gpflow.readthedocs.io/en/develop/notebooks/basics/classification.html

import tensorflow as tf
import tensorflow_probability as tfp
import gpflow
from gpflow.utilities import print_summary, set_trainable, to_default_float
gpflow.config.set_default_summary_fmt("notebook")

def testGPFlow(k):
    m = gpflow.models.VGP(
        (X, Y), 
        kernel= k,
        likelihood=gpflow.likelihoods.Bernoulli()
    )
    print("\n ########### Model before optimzation ########### \n")
    print_summary(m)

    print("\n ########### Model after optimzation ########### \n")
    opt = gpflow.optimizers.Scipy()
    res = opt.minimize(
        m.training_loss, variables=m.trainable_variables, options=dict(maxiter=2500), method="L-BFGS-B"
    )        

    print(' Message: ' + str(res.message) + '\n Status = ' + str(res.status) + '\n Number of iterations = ' + str(res.nit))
    print_summary(m)

    means, _ = m.predict_y(Xplot)  # here we only care about the mean
    y_prob = means.numpy().reshape(*xx.shape)

    print("Fitting model using GPFlow")
    plot(X,Y)

    _ = plt.contour(
        xx,
        yy,
        y_prob,
        [0.5],  # plot the p=0.5 contour line only
        colors="k",
        linewidths=1.8,
        zorder=100,
    )
k = gpflow.kernels.Linear(active_dims=[1],variance= 0.01)
testGPFlow(k)

k = gpflow.kernels.Linear(variance= 1)
testGPFlow(k)

Код GPy приведен только для справки подскажите, какой должна быть подогнанная модель. Я знаю, что GPy и GPflow используют разные методы. У меня вопрос, почему модель GPflow не подходит, когда я указываю линейное ядро ​​в 1 измерении.

1 Ответ

1 голос
/ 25 апреля 2020

Спасибо за публикацию этого вопроса, Hoang, и за использование GPflow.

Когда вы указываете input_dim в Gpy, вы указываете алгоритму действовать в двух измерениях. Active_dims в GPflow ведет себя по-разному. Он определяет, по каким измерениям вы хотите, чтобы ядро ​​действовало. 'active_dims = 1 ' говорит, что GPflow применяет ваше линейное ядро ​​только к измерению y.

Поскольку вы хотите, чтобы ваше ядро ​​работало как с измерениями x, так и y, вы следует указать active_dims = [0,1], а не просто 'active_dims = 1 .' Когда я запускаю ваш код с этим исправлением, я получаю результат, идентичный результату GPy:

enter image description here

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