forked from thuijskens/bayesian-optimization
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathplotters.py
More file actions
129 lines (103 loc) · 5.63 KB
/
plotters.py
File metadata and controls
129 lines (103 loc) · 5.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
""" plotters.py
"""
import numpy as np
import matplotlib.pyplot as plt
def plot_iteration(first_param_grid, sampled_params, sampled_loss, first_iter=0, alpha=1e-5,
greater_is_better=True, true_y=None, second_param_grid=None,
param_dims_to_plot=[0, 1], filepath=None, optimum=None):
""" plot_iteration
Plots a line plot (1D) or heatmap (2D) of the estimated loss function and expected
improvement acquisition function for each iteration of the Bayesian search algorithm.
Arguments:
----------
first_param_grid: array-like, shape = [n, 1]
Array containing the grid of points to plot for the first parameter.
sampled_params: array-like, shape = [n_points, n_params]
Points for which the value of the loss function is computed.
sampled_loss: function.
Values of the loss function for the parameters in `sampled_params`.
first_iter: int.
Only plot iterations after the `first_iter`-th iteration.
alpha: float
Variance of the error term in the GP model.
greater_is_better: boolean
Boolean indicating whether we want to maximise or minimise the loss function.
true_y: array-like, shape = [n, 1] or None
Array containing the true value of the loss function. If None, the real loss
is not plotted. (1-dimensional case)
second_param_grid: array-like, shape = [n, 1]
Array containing the grid of points to plot for the second parameter, in case
of a heatmap.
param_dims_to_plot: list of length 2
List containing the indices of `sampled_params` that contain the first and
second parameter.
optimum: array-like [1, n_params].
Maximum value of the loss function.
"""
# Create the GP
kernel = gp.kernels.Matern()
model = gp.GaussianProcessRegressor(kernel=kernel,
alpha=alpha,
n_restarts_optimizer=10,
normalize_y=True)
# Don't show the last iteration (next_sample is not available then)
for i in range(first_iter, sampled_params.shape[0] - 1):
model.fit(X=sampled_params[:(i + 1), :], y=sampled_loss[:(i + 1)])
if second_param_grid is None:
# 1-dimensional case: line plot
mu, std = model.predict(first_param_grid[:, np.newaxis], return_std=True)
ei = -1 * expected_improvement(first_param_grid, model, sampled_loss[:(i + 1)],
greater_is_better=greater_is_better, n_params=1)
fig, ax1, ax2 = _plot_loss_1d(first_param_grid, sampled_params[:(i + 1), :], sampled_loss[:(i + 1)], mu, std, ei, sampled_params[i + 1, :], yerr=alpha, true_y=true_y)
else:
# Transform grids into vectors for EI evaluation
param_grid = np.array([[first_param, second_param] for first_param in first_param_grid for second_param in second_param_grid])
mu, std = model.predict(param_grid, return_std=True)
ei = -1 * expected_improvement(param_grid, model, sampled_loss[:(i + 1)],
greater_is_better=greater_is_better, n_params=2)
fig, ax1, ax2 = _plot_loss_2d(first_param_grid, second_param_grid, sampled_params[:(i+1), param_dims_to_plot], sampled_loss, mu, ei, sampled_params[i + 1, param_dims_to_plot], optimum)
if file_path is not None:
plt.savefig('%s/bo_iteration_%d.png' % (filepath, i), bbox_inches='tight')
def _plot_loss_1d(x_grid, x_eval, y_eval, mu, std, ei, next_sample, yerr=0.0, true_y=None):
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(8,8), sharex=True)
# Loss function plot
ax1.plot(x_grid, mu, label = "GP mean")
ax1.fill_between(x_grid, mu - std, mu + std, alpha=0.5)
ax1.errorbar(x_eval, y_eval, yerr, fmt='ok', zorder=3, label="Observed values")
ax1.set_ylabel("Function value f(x)")
ax1.set_xlabel("x")
if true_y is not None:
ax1.plot(x_grid, true_y, '--', label="True function")
# Acquisition function plot
ax2.plot(x_grid, ei, 'r', label="Expected improvement")
ax2.set_ylabel("Expected improvement (EI)")
ax2.set_title("Next sample point is C = %.3f" % next_sample)
ax2.axvline(next_sample)
return fig, ax1, ax2
def _plot_loss_2d(first_param_grid, second_param_grid, sampled_params, sampled_loss, mu, ei, next_sample, optimum=None):
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(8,8), sharex=True, sharey=True)
X, Y = np.meshgrid(first_param_grid, second_param_grid, indexing='ij')
# EI contour plot
cp = ax1.contourf(X, Y, ei.reshape(X.shape))
plt.colorbar(cp, ax=ax1)
ax1.set_title("Expected Improvement. Next sample will be (%.2f, %.2f)" % (next_sample[0], next_sample[1]))
ax1.autoscale(False)
ax1.axvline(next_sample[0], color='k')
ax1.axhline(next_sample[1], color='k')
ax1.scatter(next_sample[0], next_sample[1])
ax1.set_xlabel("C")
ax1.set_ylabel("gamma")
# Loss contour plot
cp2 = ax2.contourf(X, Y, mu.reshape(X.shape))
plt.colorbar(cp2, ax=ax2)
ax2.autoscale(False)
ax2.scatter(sampled_params[:, 0], sampled_params[:, 1], zorder=1)
ax2.axvline(next_sample[0], color='k')
ax2.axhline(next_sample[1], color='k')
ax2.scatter(next_sample[0], next_sample[1])
ax2.set_title("Mean estimate of loss surface for iteration %d" % (sampled_params.shape[0]))
ax2.set_xlabel("C")
ax2.set_ylabel("gamma")
if optimum is not None:
ax2.scatter(optimum[0], optimum[1], marker='*', c='gold', s=150)
return fig, ax1, ax2