|
| 1 | +""" |
| 2 | +=================================================== |
| 3 | +Comparing initial sampling methods on integer space |
| 4 | +=================================================== |
| 5 | +
|
| 6 | +Holger Nahrstaedt 2020 Sigurd Carlsen October 2019 |
| 7 | +
|
| 8 | +.. currentmodule:: skopt |
| 9 | +
|
| 10 | +When doing baysian optimization we often want to reserve some of the |
| 11 | +early part of the optimization to pure exploration. By default the |
| 12 | +optimizer suggests purely random samples for the first n_initial_points |
| 13 | +(10 by default). The downside to this is that there is no guarantee that |
| 14 | +these samples are spread out evenly across all the dimensions. |
| 15 | +
|
| 16 | +Sampling methods as Latin hypercube, Sobol, Halton and Hammersly |
| 17 | +take advantage of the fact that we know beforehand how many random |
| 18 | +points we want to sample. Then these points can be "spread out" in |
| 19 | +such a way that each dimension is explored. |
| 20 | +
|
| 21 | +See also the example on a real space |
| 22 | +:ref:`sphx_glr_auto_examples_initial_sampling_method.py` |
| 23 | +""" |
| 24 | + |
| 25 | +print(__doc__) |
| 26 | +import numpy as np |
| 27 | +np.random.seed(1234) |
| 28 | +import matplotlib.pyplot as plt |
| 29 | +from skopt.space import Space |
| 30 | +from skopt.sampler import Sobol |
| 31 | +from skopt.sampler import Lhs |
| 32 | +from skopt.sampler import Halton |
| 33 | +from skopt.sampler import Hammersly |
| 34 | +from skopt.sampler import Grid |
| 35 | +from scipy.spatial.distance import pdist |
| 36 | + |
| 37 | +############################################################################# |
| 38 | + |
| 39 | +def plot_searchspace(x, title): |
| 40 | + fig, ax = plt.subplots() |
| 41 | + plt.plot(np.array(x)[:, 0], np.array(x)[:, 1], 'bo', label='samples') |
| 42 | + plt.plot(np.array(x)[:, 0], np.array(x)[:, 1], 'bs', markersize=40, alpha=0.5) |
| 43 | + # ax.legend(loc="best", numpoints=1) |
| 44 | + ax.set_xlabel("X1") |
| 45 | + ax.set_xlim([0, 5]) |
| 46 | + ax.set_ylabel("X2") |
| 47 | + ax.set_ylim([0, 5]) |
| 48 | + plt.title(title) |
| 49 | + ax.grid(True) |
| 50 | + |
| 51 | + |
| 52 | +n_samples = 10 |
| 53 | +space = Space([(0, 5), (0, 5)]) |
| 54 | + |
| 55 | +############################################################################# |
| 56 | +# Random sampling |
| 57 | +# --------------- |
| 58 | +x = space.rvs(n_samples) |
| 59 | +plot_searchspace(x, "Random samples") |
| 60 | +pdist_data = [] |
| 61 | +x_label = [] |
| 62 | +print("empty fields: %d" % (36 - np.size(np.unique(x, axis=0), 0))) |
| 63 | +pdist_data.append(pdist(x).flatten()) |
| 64 | +x_label.append("random") |
| 65 | + |
| 66 | +############################################################################# |
| 67 | +# Sobol |
| 68 | +# ----- |
| 69 | + |
| 70 | +sobol = Sobol() |
| 71 | +x = sobol.generate(space.dimensions, n_samples) |
| 72 | +plot_searchspace(x, 'Sobol') |
| 73 | +print("empty fields: %d" % (36 - np.size(np.unique(x, axis=0), 0))) |
| 74 | +pdist_data.append(pdist(x).flatten()) |
| 75 | +x_label.append("sobol") |
| 76 | + |
| 77 | +############################################################################# |
| 78 | +# Classic latin hypercube sampling |
| 79 | +# -------------------------------- |
| 80 | + |
| 81 | +lhs = Lhs(lhs_type="classic", criterion=None) |
| 82 | +x = lhs.generate(space.dimensions, n_samples) |
| 83 | +plot_searchspace(x, 'classic LHS') |
| 84 | +print("empty fields: %d" % (36 - np.size(np.unique(x, axis=0), 0))) |
| 85 | +pdist_data.append(pdist(x).flatten()) |
| 86 | +x_label.append("lhs") |
| 87 | + |
| 88 | +############################################################################# |
| 89 | +# Centered latin hypercube sampling |
| 90 | +# --------------------------------- |
| 91 | + |
| 92 | +lhs = Lhs(lhs_type="centered", criterion=None) |
| 93 | +x = lhs.generate(space.dimensions, n_samples) |
| 94 | +plot_searchspace(x, 'centered LHS') |
| 95 | +print("empty fields: %d" % (36 - np.size(np.unique(x, axis=0), 0))) |
| 96 | +pdist_data.append(pdist(x).flatten()) |
| 97 | +x_label.append("center") |
| 98 | + |
| 99 | +############################################################################# |
| 100 | +# Maximin optimized hypercube sampling |
| 101 | +# ------------------------------------ |
| 102 | + |
| 103 | +lhs = Lhs(criterion="maximin", iterations=10000) |
| 104 | +x = lhs.generate(space.dimensions, n_samples) |
| 105 | +plot_searchspace(x, 'maximin LHS') |
| 106 | +print("empty fields: %d" % (36 - np.size(np.unique(x, axis=0), 0))) |
| 107 | +pdist_data.append(pdist(x).flatten()) |
| 108 | +x_label.append("maximin") |
| 109 | + |
| 110 | +############################################################################# |
| 111 | +# Correlation optimized hypercube sampling |
| 112 | +# ---------------------------------------- |
| 113 | + |
| 114 | +lhs = Lhs(criterion="correlation", iterations=10000) |
| 115 | +x = lhs.generate(space.dimensions, n_samples) |
| 116 | +plot_searchspace(x, 'correlation LHS') |
| 117 | +print("empty fields: %d" % (36 - np.size(np.unique(x, axis=0), 0))) |
| 118 | +pdist_data.append(pdist(x).flatten()) |
| 119 | +x_label.append("corr") |
| 120 | + |
| 121 | +############################################################################# |
| 122 | +# Ratio optimized hypercube sampling |
| 123 | +# ---------------------------------- |
| 124 | + |
| 125 | +lhs = Lhs(criterion="ratio", iterations=10000) |
| 126 | +x = lhs.generate(space.dimensions, n_samples) |
| 127 | +plot_searchspace(x, 'ratio LHS') |
| 128 | +print("empty fields: %d" % (36 - np.size(np.unique(x, axis=0), 0))) |
| 129 | +pdist_data.append(pdist(x).flatten()) |
| 130 | +x_label.append("ratio") |
| 131 | + |
| 132 | +############################################################################# |
| 133 | +# Halton sampling |
| 134 | +# --------------- |
| 135 | + |
| 136 | +halton = Halton() |
| 137 | +x = halton.generate(space.dimensions, n_samples) |
| 138 | +plot_searchspace(x, 'Halton') |
| 139 | +print("empty fields: %d" % (36 - np.size(np.unique(x, axis=0), 0))) |
| 140 | +pdist_data.append(pdist(x).flatten()) |
| 141 | +x_label.append("halton") |
| 142 | + |
| 143 | +############################################################################# |
| 144 | +# Hammersly sampling |
| 145 | +# ------------------ |
| 146 | + |
| 147 | +hammersly = Hammersly() |
| 148 | +x = hammersly.generate(space.dimensions, n_samples) |
| 149 | +plot_searchspace(x, 'Hammersly') |
| 150 | +print("empty fields: %d" % (36 - np.size(np.unique(x, axis=0), 0))) |
| 151 | +pdist_data.append(pdist(x).flatten()) |
| 152 | +x_label.append("hammersly") |
| 153 | + |
| 154 | +############################################################################# |
| 155 | +# Grid sampling |
| 156 | +# ------------- |
| 157 | + |
| 158 | +grid = Grid(border="include", use_full_layout=False) |
| 159 | +x = grid.generate(space.dimensions, n_samples) |
| 160 | +plot_searchspace(x, 'Grid') |
| 161 | +print("empty fields: %d" % (36 - np.size(np.unique(x, axis=0), 0))) |
| 162 | +pdist_data.append(pdist(x).flatten()) |
| 163 | +x_label.append("grid") |
| 164 | + |
| 165 | +############################################################################# |
| 166 | +# Pdist boxplot of all methods |
| 167 | +# ---------------------------- |
| 168 | +# |
| 169 | +# This boxplot shows the distance between all generated points using |
| 170 | +# Euclidian distance. The higher the value, the better the sampling method. |
| 171 | +# It can be seen that random has the worst performance |
| 172 | + |
| 173 | +fig, ax = plt.subplots() |
| 174 | +ax.boxplot(pdist_data) |
| 175 | +plt.grid(True) |
| 176 | +plt.ylabel("pdist") |
| 177 | +_ = ax.set_ylim(0, 6) |
| 178 | +_ = ax.set_xticklabels(x_label, rotation=45, fontsize=8) |
0 commit comments