Code Monkey home page Code Monkey logo

gpro's Introduction

Preference learning with Gaussian processes.

Build Status Codecov MIT license

Python implementation of a probabilistic kernel approach to preference learning based on Gaussian processes. Preference relations are captured in a Bayesian framework which allows in turn for global optimization of the inferred functions (Gaussian processes) in as few iterations as possible.

Installation.

Installation

  • From PyPI:

    pip install GPro
    
  • From GitHub:

    pip install git+https://github.com/chariff/GPro.git
    

Dependencies

GPro requires:

  • Python (>= 3.5)
  • NumPy+mkl (>= 1.9.0)
  • SciPy (< 1.5.0)
  • Pandas (>= 0.24.0)

Brief guide to using GPro.

Checkout the package docstrings for more information.

1. Fitting and making Predictions.

from GPro.preference import ProbitPreferenceGP
import numpy as np
import matplotlib.pyplot as plt

Training data consisting of numeric real positive values. A minimum of two values is required. The following example is in 1D.

X = np.array([2, 1]).reshape(-1, 1)

M is an array containing preferences. A preference is an array of positive integers of shape = (2,). The left integer of a given preference is the index of a value in X which is preferred over another value of X indexed by the right integer of the same preference array. In the following example, 2 is preferred over 1.

M = np.array([0, 1]).reshape(-1, 2)

Instantiate a ProbitPreferenceGP object with default parameters.

gpr = ProbitPreferenceGP()

Fit a Gaussian process. A flat prior with mean zero is applied by default.

gpr.fit(X, M, f_prior=None)

Predict new values.

X_new = np.linspace(-6, 9, 100).reshape(-1, 1)
predicted_values, predicted_deviations = gpr.predict(X_new, return_y_std=True)

Plot.

plt.plot(X_new, np.zeros(100), 'k--', label='GP predictive prior')
plt.plot(X_new, predicted_values, 'r-', label='GP predictive posterior')
plt.plot(X.flat, gpr.predict(X).flat, 'bx', label='Preference')
plt.ylabel('f(X)')
plt.xlabel('X')
# the predicted s.d. is divided for an aesthetic purpose.
plt.gca().fill_between(X_new.flatten(),
                       (predicted_values - predicted_deviations / 50).flatten(),
                       (predicted_values + predicted_deviations / 50).flatten(),
                       color="#b0e0e6", label='GP predictive posterior s.d.')
plt.legend()
plt.show()

The following plot shows how the posterior predictive Gaussian process is adjusted to the data i.e. 2 is preferred to 1. One can also notice how the standard deviation is small where there is data.

Gaussian process posterior

2. Interactive bayesian optimization.

Preference relations are captured in a Bayesian framework which allows for global optimization of the latent function (modelized by Gaussian processes) describing the preference relations. Interactive bayesian optimization with probit responses works by querying the user with a paired comparison and by subsequently updating the Gaussian process model. The iterative procedure optimizes a utility function, seeking a balance between exploration and exploitation of the latent function, to present the user with a new set of instances.

from GPro.kernels import Matern
from GPro.posterior import Laplace
from GPro.acquisitions import UCB
from GPro.optimization import ProbitBayesianOptimization
import numpy as np

# 3D example. Initialization.
X = np.random.sample(size=(2, 3)) * 10
M = np.array([0, 1]).reshape(-1, 2)

Custom parameters for the ProbitBayesianOptimization object. Checkout the package docstrings for more informations on the parameters.

GP_params = {'kernel': Matern(length_scale=1, nu=2.5),
             'post_approx': Laplace(s_eval=1e-5, max_iter=1000,
                                    eta=0.01, tol=1e-3),
             'acquisition': UCB(kappa=2.576),
             'alpha': 1e-5,
             'random_state': None}

Instantiate a ProbitBayesianOptimization object with custom parameters.

gpr_opt = ProbitBayesianOptimization(X, M, GP_params)

Bounded region of optimization space.

bounds = {'x0': (0, 10), 'x1': (0, 10), 'x2': (0, 10)}

Interactive optimization method. Checkout the package docstrings for more informations on the parameters.

console_opt = gpr_opt.interactive_optimization(bounds=bounds, n_init=100, n_solve=10)
optimal_values, suggestion, X_post, M_post, f_post = console_opt
print('optimal values: ', optimal_values)
>>>                   x0        x1        x2
>>> preference  0.306996  3.581879  4.844135
>>> suggestion  0.000000  2.749200  3.287625
>>> Iteration 0, preference (p) or suggestion (s)? (Q to quit): p
>>>                   x0        x1        x2
>>> preference  0.306996  3.581879  4.844135
>>> suggestion  0.289541  4.118421  6.052125
>>> Iteration 1, preference (p) or suggestion (s)? (Q to quit): s
>>>                   x0        x1        x2
>>> preference  0.289541  4.118421  6.052125
>>> suggestion  1.601063  4.300604  5.208000
>>> Iteration 2, preference (p) or suggestion (s)? (Q to quit): Q
>>> optimal values:  [0.28954095 4.11842105 6.05212487]

One can use informative prior. Let's use posterior as prior for the sake of example.

gpr_opt = ProbitBayesianOptimization(X_post, M_post, GP_params)
console_opt = gpr_opt.interactive_optimization(bounds=bounds, n_init=100, 
                                               n_solve=10, f_prior=f_post,
                                               max_iter=1, print_suggestion=False)
optimal_values, suggestion, X_post, M_post, f_post = console_opt
print('optimal values: ', optimal_values)
>>>                   x0        x1        x2
>>> preference  0.289541  4.118421  6.052125
>>> suggestion  1.601063  4.300604  5.208000
>>> Iteration 2, preference (p) or suggestion (s)? (Q to quit): Q
>>> optimal values:  [0.28954095 4.11842105 6.05212487]

Download the algorithm with a GUI fully written in python on

2. Bayesian optimization of a black-box function.

Disclaimer: For testing purposes, we maximize a multivariate normal pdf.

from GPro.kernels import Matern
from GPro.posterior import Laplace
from GPro.acquisitions import UCB
from GPro.optimization import ProbitBayesianOptimization
from scipy.stats import multivariate_normal
import numpy as np
from sklearn import datasets
import matplotlib.cm as cm
import matplotlib.pyplot as plt

Uniform sampling given bounds.

def random_sample(n, d, bounds, random_state=None):
    if random_state is None:
        random_state = np.random.randint(1e6)
    random_state = np.random.RandomState(random_state)
    sample = random_state.uniform(bounds[:, 0], bounds[:, 1],
                                  size=(n, d))
    return sample

Sample parameters of a multivariate normal distribution.

def sample_normal_params(n, d, bounds, scale_sigma=1, random_state=None):
    # sample centroids.
    mu = random_sample(n=n, d=d, bounds=np.array(list(bounds.values())),
                       random_state=random_state)
    # sample covariance matrices.
    sigma = datasets.make_spd_matrix(d, random_state) * scale_sigma
    theta = {'mu': mu, 'sigma': sigma}
    return theta

Example is in 2 dimensions.

d = 2
# Bounded region of optimization space.
bounds = {'x' + str(i): (0, 10) for i in range(0, d)}
# Sample parameters of a d-multivariate normal distribution
theta = sample_normal_params(n=1, d=d, bounds=bounds, scale_sigma=10, random_state=12)
# function to be optimized.
f = lambda x: multivariate_normal.pdf(x, mean=theta['mu'][0], cov=theta['sigma'])
# X, M, init
X = random_sample(n=2, d=d, bounds=np.array(list(bounds.values())))
X = np.asarray(X, dtype='float64')
# Target choices. A preference is an array of positive
# integers of shape = (2,). preference[0], is an index
# of X preferred over preference[1], which is an index of X.
M = sorted(range(len(f(X))), key=lambda k: f(X)[k], reverse=True)
M = np.asarray([M], dtype='int8')
# Parameters for the ProbitBayesianOptimization object.
GP_params = {'kernel': Matern(length_scale=1, nu=2.5),
             'post_approx': Laplace(s_eval=1e-5, max_iter=1000,
                                    eta=0.01, tol=1e-3),
             'acquisition': UCB(kappa=2.576),
             'alpha': 1e-5,
             'random_state': None}
# instantiate a ProbitBayesianOptimization object with custom parameters
gpr_opt = ProbitBayesianOptimization(X, M, GP_params)

Function optimization method.

function_opt = gpr_opt.function_optimization(f=f, bounds=bounds, max_iter=50,
                                             n_init=1000, n_solve=1)

optimal_values, X_post, M_post, f_post = function_opt
print('optimal values: ', optimal_values)
>>> optimal values:  [1.45340052 7.22687626]
# rmse
print('rmse: ', .5 * sum(np.sqrt((optimal_values - theta['mu'][0]) ** 2)))
>>> rmse:  0.13092430596422377
# 2d plot
if d == 2:
    resolution = 10
    x_min, x_max = bounds['x0'][0], bounds['x0'][1]
    y_min, y_max = bounds['x1'][0], bounds['x1'][1]
    x = np.linspace(x_min, x_max, resolution)
    y = np.linspace(y_min, y_max, resolution)
    X, Y = np.meshgrid(x, y)
    grid = np.empty((resolution ** 2, 2))
    grid[:, 0] = X.flat
    grid[:, 1] = Y.flat
    Z = f(grid)
    plt.imshow(Z.reshape(-1, resolution), interpolation="bicubic",
               origin="lower", cmap=cm.rainbow, extent=[x_min, x_max, y_min, y_max])
    plt.scatter(optimal_values[0], optimal_values[1], color='black', s=10)
    plt.title('Target function')
    plt.colorbar()
    plt.show()

References:

gpro's People

Contributors

chariff avatar krisnguyen135 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.