Created
March 6, 2017 07:37
-
-
Save iaroslav-ai/ded34b4e492f1b5dc8e9ddbe3c5cb166 to your computer and use it in GitHub Desktop.
Knowledge transfer for sequential model based optimization
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from scipy.optimize import minimize, basinhopping, differential_evolution | |
import numpy as np | |
from autograd import numpy as np, grad | |
class SkoptProxy(): | |
def __init__(self, ModelClass, bounds): | |
self.ModelClass = ModelClass | |
self.X = [] | |
self.Y = [] | |
self.C = [] | |
self.context = None | |
self.bounds = bounds | |
def sample(self): | |
r = np.array([np.random.uniform(a,b) for a, b in self.bounds]) | |
return r | |
def set_context(self, c): | |
self.context = c | |
def concat_context(self, C, X): | |
return np.column_stack([C, X]) | |
def ask(self): | |
X, Y = self.X, self.Y | |
i = len(Y) | |
if i < 10: | |
x = self.sample() | |
return x | |
X = self.concat_context(self.C, X) | |
model = GaussianProcessRegressor(kernel=Matern()) | |
model = model.fit(X, Y) | |
y_opt = np.min(Y) | |
def acquisition_function(x): | |
x = self.concat_context([self.context], [x]) | |
exploitation, exploration = model.predict(x, return_std=True) | |
result = exploitation[0] - exploration[0] # ((i%3)/2.0)* | |
return result | |
# find some random x's with good values | |
values = [] | |
for i in range(128): | |
x = self.sample() | |
y = acquisition_function(x) | |
values.append((x, y)) | |
values.sort(key=lambda v: v[1]) | |
best_est = np.inf | |
best_par = None | |
# select the best random points | |
for x0, y0 in values[:5]: | |
x = minimize(acquisition_function, x0, bounds=self.bounds).x | |
y = acquisition_function(x) | |
if y < best_est: | |
best_est = y | |
best_par = x | |
return best_par | |
def tell(self, x, y): | |
self.X.append(x) | |
self.Y.append(y) | |
self.C.append(self.context) | |
from skopt import space | |
from sklearn.svm import SVR | |
class MultiTaskOptProb(): | |
def __init__(self): | |
self.space = { | |
'C': space.Real(-5.0, 5.0), | |
'gamma': space.Real(-5.0, 5.0), | |
'epsilon': space.Real(-5.0, 5.0), | |
} | |
self.idx = 0 | |
def reset(self): | |
X = np.random.randn(256, 5) | |
w = np.random.rand(5) | |
Y = np.dot(X, w) | |
pw = np.random.uniform(1.0, 2.0) | |
nz = np.random.uniform(0.1, 1.0) | |
Y = np.sign(Y) * (np.abs(Y) ** pw) | |
Y = Y + np.random.randn(len(Y))*nz | |
I = np.random.rand(len(X)) < 0.6 | |
X, Xv = X[I], X[~I] | |
Y, Yv = Y[I], Y[~I] | |
z = np.zeros(10) | |
z[self.idx] = 1.0 | |
self.idx += 1 | |
self.data = X, Y, Xv, Yv | |
# return task specific features | |
return np.concatenate([z]) # , [pw], [nz] | |
def step(self, P): | |
params = {k:10**p for k,p in zip(self.space.keys(), P)} | |
model = SVR(**params) | |
X, Y, Xv, Yv = self.data | |
model.fit(X, Y) | |
score = model.score(Xv, Yv) | |
return -score | |
import json | |
from skopt import Optimizer | |
from skopt.learning import GaussianProcessRegressor, RandomForestRegressor, ExtraTreesRegressor | |
import random | |
from skopt.learning.gaussian_process.kernels import Matern | |
MAX_SUBPROBLEM_STEPS=24 | |
MAX_SIMILAR_TASKS=8 | |
REPEATS = 5 | |
recalculate = True | |
results_file = 'results.json' | |
if recalculate: | |
results = {} | |
for rep in range(REPEATS): | |
spc = MultiTaskOptProb().space | |
def get_skopt_optimizer(): | |
return Optimizer( | |
[spc[k] for k in spc.keys()], | |
GaussianProcessRegressor(kernel=Matern()), | |
acq_optimizer="lbfgs" | |
) | |
A = SkoptProxy(GaussianProcessRegressor, [(spc[k].low, spc[k].high) for k in spc.keys()]) | |
B = get_skopt_optimizer() | |
for solver in [A, B]: | |
task = MultiTaskOptProb() | |
if not solver.__class__.__name__ in results: | |
results[solver.__class__.__name__] = [] | |
for similar_task in range(MAX_SIMILAR_TASKS): | |
print("Episode " + str(similar_task)) | |
trace = [] | |
best_y = np.inf | |
context = task.reset() | |
try: | |
solver.set_context(context) | |
except AttributeError: | |
solver = get_skopt_optimizer() | |
for i in range(MAX_SUBPROBLEM_STEPS): | |
P = solver.ask() | |
try: | |
v = task.step(P) | |
except BaseException as ex: | |
v = 1.0 | |
print ex | |
if best_y > v: | |
best_y = v | |
best_x = P | |
print("#" + str(i) + ", "+ str(best_y)) | |
try: | |
solver.tell(P, v) | |
except BaseException as ex: | |
pass | |
trace.append(float(best_y)) | |
results[solver.__class__.__name__].append(trace) | |
else: | |
results = json.load(open(results_file)) | |
with open(results_file, 'w') as f: | |
json.dump(results, f) | |
colors = ['red', 'blue'] | |
name_maps = {SkoptProxy.__name__:'GP, Knowledge transfer', Optimizer.__name__:'Skopt GP, from scratch'} | |
def visualize_results(results): | |
import matplotlib.pyplot as plt | |
for k, c in zip(results.keys(), colors): | |
y = np.mean(results[k], axis=0) | |
x = range(len(y)) | |
plt.scatter(x, y, c=c, label=name_maps[k]) | |
plt.xlabel('Iteration') | |
plt.ylabel('Avg. objective') | |
plt.grid() | |
plt.legend() | |
plt.show() | |
visualize_results(results) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment