Bayes-Optimierung (Referenz: Einführung in die Bayes-Optimierung, [Einführung in die Bayes-Optimierung für maschinelles Lernen](https://book.mynavi.jp/ Durch die Verwendung von manatee / detail / id = 59393)) besteht die Möglichkeit, dass Sie effizient nach Hyperparametern suchen können, die während des maschinellen Lernens von verschiedenen Try & Error festgelegt werden müssen.
Ich kann die Idee usw. dank der Zunahme verschiedener Kommentarartikel in letzter Zeit verstehen, aber ich konnte sie nicht in Form der GridSearch-Bibliothek im Web finden, also habe ich sie dieses Mal gemacht. Ich bin sicher, es ist eine Neuerfindung der Räder, aber ich bin froh, dass die Neuerfindung eine Lernerfahrung ist.
bayesian_optimizer.py
from itertools import product
from sklearn.gaussian_process import GaussianProcess
# The MIT License (C) 2016 mokemokechicken
class BayesianOptimizer:
x_list = None
y_list = None
yielding_index = None
k_band = 5
verbose = False
def __init__(self, params):
self.params = params
self.keys = []
self.values = []
for k, v in sorted(self.params.items()):
self.keys.append(k)
self.values.append(v)
@property
def n_pattern(self):
return len(list(product(*self.values)))
def output(self, *args, **kwargs):
if self.verbose:
print(*args, **kwargs)
def supply_next_param(self, max_iter=None):
self.x_list = []
self.y_list = []
all_parameters = list(product(*self.values)) # [(0.01, [0, 0], 0, [10, 10]), (0.01, [0, 0], 0, [15, 15]), ...
index_space = [list(range(len(v))) for v in self.values] # [[0], [0, 1, 2], [0], [0, 1, 2]]
all_index_list = list(product(*index_space)) # [(0, 0, 0, 0), (0, 0, 0, 1), ...
# examine 2 random points initially
idx = list(range(len(all_index_list)))
np.random.shuffle(idx)
searched_index_list = []
for index in idx[:2]:
param = self.to_param(all_parameters[index])
self.yielding_index = all_index_list[index]
searched_index_list.append(index)
yield param
# Bayesian Optimization
max_iter = int(min(max_iter or max(np.sqrt(self.n_pattern)*4, 20), self.n_pattern)) #Berechnen Sie die maximale Anzahl von Suchvorgängen entsprechend.
for iteration in range(max_iter):
k = 1 + np.exp(-iteration / max_iter * 3) * self.k_band #Reduzieren Sie schrittweise den Wert von k, um die Suche hervorzuheben → konzentrieren Sie sich auf die Nutzung
gp = self.create_gp_and_fit(np.array(self.x_list), np.array(self.y_list))
mean_array, mse_array = gp.predict(all_index_list, eval_MSE=True)
next_index, acq_array = self.acquisition(mean_array, mse_array, k, excludes=searched_index_list)
self.output("--- Most Expected Predictions")
for acq, ps in sorted(zip(acq_array, all_parameters), reverse=True)[:3]:
self.output("%.2f: %s" % (acq, list(zip(self.keys, ps))))
self.output("--- Past Best Results")
for acq, vs, ps in self.best_results(3):
self.output("%.2f: %s" % (acq, list(zip(self.keys, vs))))
if next_index in searched_index_list:
break
searched_index_list.append(next_index)
self.yielding_index = all_index_list[next_index]
yield self.to_param(all_parameters[next_index])
@staticmethod
def create_gp_and_fit(x, y, max_try=100):
#Verdächtig hier
theta0 = 0.1
for i in range(max_try+1):
try:
gp = GaussianProcess(theta0=theta0)
gp.fit(x, y)
return gp
except Exception as e:
theta0 *= 10
if i == max_try:
print(theta0)
raise e
def to_param(self, row):
return dict(zip(self.keys, row))
def report(self, score):
self.x_list.append(self.yielding_index)
self.y_list.append(score)
def best_results(self, n=5):
index_list = []
param_list = []
for xs in self.x_list:
values = [self.values[i][x] for i, x in enumerate(xs)]
index_list.append(values)
param_list.append(self.to_param(values))
return sorted(zip(self.y_list, index_list, param_list), reverse=True)[:n]
@staticmethod
def acquisition(mean_array, mse_array, k, excludes=None):
excludes = excludes or []
values = mean_array + np.sqrt(mse_array) * k
for_argmax = np.copy(values)
for ex in excludes:
for_argmax[ex] = -np.Inf
return np.argmax(for_argmax), values
Die grundlegende Verwendung ist wie folgt.
params = {
"parameter1": [10, 20, 25, 50],
"parameter2": ['p1', 'p2'],
...
}
bo = BayesianOptimizer(params) #Übergeben Sie eine Kombination von Parametern in einem Wörterbuch
for param in bo.supply_next_param(): #Der Parameter, der als nächstes überprüft werden soll, wird von dict übergeben
y = unknown_score_function(param) #Bewerten Sie den Parameter auf irgendeine Weise
bo.report(y) #Ich werde Ihnen den Bewertungswert mitteilen
print(bo.best_results()) #Ich erinnere mich an den besten Score-Wert und Parameter
Folgendes habe ich mit dem Jupyter-Notebook versucht, um festzustellen, ob es funktioniert. https://gist.github.com/mokemokechicken/7f3cf33c71d33bf0ec242c37cb3f2a75
Bereiten Sie nach mehreren Wellen mit sin und cos in der folgenden 50 x 50-Ebene einen leicht ungleichmäßigen zweidimensionalen Raum mit Rauschen vor.
Der Teil mit dem roten Punkt (Zeile = 3, Spalte = 29) ist der Punkt mit dem höchsten Wert.
Ich werde so vorgehen. Die Anzahl der Suchvorgänge beträgt 200.
Zunächst untersuche ich den gesamten Raum. Ein wenig Go-like w.
Glücklicherweise scheint er mehrmals in der Nähe seines Favoriten in der Mitte gesucht zu haben.
Der Lieblingspunkt wurde ziemlich viel untersucht.
Überprüfen Sie sorgfältig den anderen Berg unten links, der gut aussieht. Der Bereich um den Favoriten in der Mitte ist ebenfalls abgedeckt.
Überprüfen Sie die leeren Stellen auf alles andere, was gut aussieht.
Es gibt nichts anderes, was besonders gut zu sein scheint und es endet. Nun, selbst wenn Menschen es tun, sieht es so aus.
Wenn ich es mache, scheint es, dass es in einer Vielzahl von Szenen verwendet werden kann. Das Leben ist so.