[PYTHON] [Übersetzung] Hyperopt-Tutorial

Tutorial ([wiki: FMin rev: a663e] in der Python-Bibliothek hyperopt zur Optimierung böser Suchräume in realen, diskreten und bedingten Dimensionen (https://github.com/hyperopt/hyperopt) (https://github.com/hyperopt/hyperopt/wiki/FMin/a663e64546eb5cd3ed462618dcc1e41863ad8688)) wurde von Google übersetzt. Lizenz


Diese Seite ist ein Tutorial zur grundlegenden Verwendung von "hyperopt.fmin ()". Beschreibt, wie eine Zielfunktion geschrieben wird, die fmin optimieren kann, und wie ein Suchraum geschrieben wird, den fmin durchsuchen kann.

Die Aufgabe von Hyperopt besteht darin, den bestmöglichen stochastischen Funktionswert für einen Skalarwert zu finden und nicht die Menge möglicher Argumente für diese Funktion. Während viele Optimierungspakete erwarten, dass diese Eingaben aus dem Vektorraum abgeleitet werden, empfiehlt Hyperopt, Ihren Suchraum detaillierter zu beschreiben. Durch die Bereitstellung weiterer Informationen darüber, wo Ihre Funktion definiert ist und wo der optimale Wert liegt, können die Algorithmen von hyperopt effizienter gesucht werden.

Die Möglichkeit, Hyperopt zu verwenden, besteht darin, Folgendes zu schreiben:

Dieses (grundlegendste) Tutorial zeigt Ihnen, wie Sie Funktionen und Suchräume mithilfe der Standard-Testdatenbank und des Dummy-Zufallssuchalgorithmus erstellen. In Abschnitt (1) geht es um verschiedene Aufrufkonventionen für die Kommunikation zwischen der Zielfunktion und Hyperopt. In Abschnitt (2) geht es um die Beschreibung des Suchraums.

Eine parallele Suche ist möglich, indem die Datenbank "Trials" durch die Datenbank "MongoTrials" ersetzt wird. Es gibt eine weitere Wiki-Seite über die Verwendung von Mongodb für parallele Suchvorgänge.

Die Auswahl eines Suchalgorithmus ist so einfach wie die Übergabe von "algo = hyperopt.tpe.suggest" anstelle von "algo = hyperopt.random.suggest". Der Suchalgorithmus ist eigentlich ein aufrufbares Objekt, und sein Konstruktor akzeptiert Konfigurationsargumente, bei denen es darum geht, wie der Suchalgorithmus ausgewählt wird.

1. Definition der zu minimierenden Funktion

Hyperopt bietet mehrere Ebenen erhöhter Flexibilität und Komplexität bei der Angabe, um die Zielfunktion zu minimieren. Fragen, über die man als Designer nachdenken sollte

In den nächsten Abschnitten werden verschiedene Möglichkeiten zur Implementierung von Zielen untersucht, mit denen das quadratische Ziel für eine einzelne Variable minimiert wird. Suchen Sie in jedem Abschnitt im Bereich von -10 bis +10. Dies kann in * Suchraum * beschrieben werden.

space = hp.uniform('x', -10, 10)

Below, Section 2, covers how to specify search spaces that are more complicated.

1.1 Der einfachste Fall

Das einfachste Protokoll für die Kommunikation zwischen dem Optimierungsalgorithmus von hyperopt und der Zielfunktion besteht darin, dass die Zielfunktion einen gültigen Punkt aus dem Suchraum empfängt und diesem Punkt ein Gleitkomma-Verlust (auch als negatives Dienstprogramm bezeichnet) zugeordnet ist. Rückkehr.

from hyperopt import fmin, tpe, hp
best = fmin(fn=lambda x: x ** 2,
    space=hp.uniform('x', -10, 10),
    algo=tpe.suggest,
    max_evals=100)
print best

Dieses Protokoll hat den Vorteil, dass es sehr gut lesbar und einfach zu tippen ist. Wie Sie sehen können, ist es fast ein Liner. Der Nachteil dieses Protokolls ist (1) Mit dieser Art von Funktion können keine zusätzlichen Informationen zu jeder Bewertung an die Testdatenbank zurückgegeben werden. Und (2) Diese Art von Funktion kann nicht mit Suchalgorithmen oder anderen parallelen Funktionsbewertungen interagieren. Das folgende Beispiel zeigt, warum Sie diese Dinge tun möchten.

1.2 Anhängen zusätzlicher Informationen nach Testobjekt

Wenn die Zielfunktion komplex ist und die Ausführung lange dauert, möchten Sie möglicherweise mehr statistische und diagnostische Informationen sowie den letzten Gleitkommaverlust speichern. In solchen Fällen kann die Funktion fmin das Wörterbuch als Rückgabewert behandeln. Das bedeutet, dass Ihre Verlustfunktion ein Wörterbuch zurückgeben kann, das alle gewünschten Statistiken und Diagnosen verschachtelt. Die Realität ist etwas weniger flexibel. Wenn Sie beispielsweise mongodb verwenden, muss das Wörterbuch ein gültiges JSON-Dokument sein. Dennoch gibt es viel Flexibilität, um domänenspezifische Hilfsergebnisse zu speichern.

Wenn die Zielfunktion ein Wörterbuch zurückgibt, sucht die Funktion fmin nach einigen speziellen Schlüssel / Wert-Paaren im Rückgabewert und übergibt sie an den Optimierungsalgorithmus. Es sind zwei Schlüssel-Wert-Paare erforderlich.

Die Funktion fmin reagiert auch auf einige Optionstasten:

Wörterbücher verwenden eine Vielzahl von Back-End-Speichermechanismen. Sie müssen daher sicherstellen, dass sie mit JSON kompatibel sind. Wenn es sich um ein Diagramm mit einer Baumstruktur aus Wörterbuch, Liste, Tapple, Nummer, Zeichenfolge, Datum und Uhrzeit handelt, gibt es kein Problem.

** Hinweis: ** Um numpy Arrays zu speichern, sollten Sie sie in Strings serialisieren und als Anhänge speichern.

Das Schreiben der obigen Funktion in einem Stil, der ein Wörterbuch zurückgibt, sieht folgendermaßen aus:

import pickle
import time
from hyperopt import fmin, tpe, hp, STATUS_OK

def objective(x):
    return {'loss': x ** 2, 'status': STATUS_OK }

best = fmin(objective,
    space=hp.uniform('x', -10, 10),
    algo=tpe.suggest,
    max_evals=100)

print best

1.3 Versuchsobjekt

Um den Zweck der Rückgabe eines Wörterbuchs tatsächlich zu erkennen, ändern Sie die Zielfunktion, um einige zurückzugeben, und übergeben Sie ein explizites Argument "Versuche" an "fmin".

import pickle
import time
from hyperopt import fmin, tpe, hp, STATUS_OK, Trials

def objective(x):
    return {
        'loss': x ** 2,
        'status': STATUS_OK,
        # -- store other results like this
        'eval_time': time.time(),
        'other_stuff': {'type': None, 'value': [0, 1, 2]},
        # -- attachments are handled differently
        'attachments':
            {'time_module': pickle.dumps(time.time)}
        }
trials = Trials()
best = fmin(objective,
    space=hp.uniform('x', -10, 10),
    algo=tpe.suggest,
    max_evals=100,
    trials=trials)

print best

In diesem Fall ist der Aufruf von fmin derselbe wie zuvor, Sie können das Testobjekt jedoch direkt übergeben, um alle während des Experiments berechneten Rückgabewerte zu überprüfen.

Also zum Beispiel:

Sie können dieses Testobjekt speichern, an eine integrierte Plotroutine übergeben oder mit Ihrem eigenen benutzerdefinierten Code analysieren.

"Anhänge" werden von einem speziellen Mechanismus verwaltet, mit dem der gleiche Code sowohl für "Versuche" als auch für "MongoTrials" verwendet werden kann.

Sie können einen solchen Testanhang erhalten. Dies wird das Zeitmodul für den 5. Versuch erhalten.

msg = trials.trial_attachments(trials.trials[5])['time_module']
time_module = pickle.loads(msg)

Anhänge sind große Zeichenfolgen. Wenn Sie also MongoTrials verwenden, müssen Sie nicht mehr herunterladen, als Sie benötigen. Strings können auch global über Versuche an das gesamte Testobjekt angehängt werden. Anhänge verhalten sich wie ein String-zu-String-Wörterbuch.

** NB ** Derzeit werden versuchsspezifische Anhänge an Testobjekte im Anhangswörterbuch für denselben globalen Test abgelegt, können sich jedoch in Zukunft ändern und gelten nicht für MongoTrials.

1.4 Strg-Objekt für die Echtzeitkommunikation mit MongoDB

Es ist möglich, dass fmin () Ihrer Zielfunktion den Griff von Mongodb gibt, der in parallelen Experimenten verwendet wird. Mit diesem Mechanismus können Sie die Datenbank mit Teilergebnissen aktualisieren und mit anderen parallelen Prozessen kommunizieren, die unterschiedliche Punkte bewerten. Die Zielfunktion kann sogar neue Suchpunkte hinzufügen, z. B. "random.suggest".

Die grundlegenden Techniken sind:

Ich werde es in diesem kurzen Tutorial nicht behandeln, aber ich möchte erwähnen, was mit der aktuellen Codebasis möglich ist. Es enthält auch Hyperopt-Quellen, Unit-Tests und Beispielprojekte wie hyperopt-convnet. Bitte senden Sie mir eine E-Mail oder senden Sie ein Github-Problem, um diesen Teil des Codes zu beschleunigen.

2. Definition des Suchraums

Der Suchraum besteht aus verschachtelten funktionalen Ausdrücken, die probabilistische Ausdrücke enthalten. Die probabilistische Darstellung ist ein Hyperparameter. Die Abtastung aus diesem verschachtelten stochastischen Programm definiert einen Zufallssuchalgorithmus. Der Hyperparameter-Optimierungsalgorithmus ersetzt die übliche "Abtast" -Logik durch eine adaptive Suchstrategie und versucht nicht, aus der angegebenen Verteilung im Suchraum abzutasten.

Stellen Sie sich den Suchraum am besten als ein Stichprobenprogramm für probabilistische Argumente vor. Zum Beispiel

from hyperopt import hp
space = hp.choice('a',
    [
        ('case 1', 1 + hp.lognormal('c1', 0, 1)),
        ('case 2', hp.uniform('c2', -10, 10))
    ])

Das Ergebnis der Ausführung dieses Codes ist die Variable "Leerzeichen", die auf das Diagramm der Ausdruckskennung und ihre Argumente verweist. Es wurde tatsächlich nichts probiert. Es ist nur eine Grafik, die beschreibt, wie Punkte abgetastet werden. Der Code für die Arbeit mit dieser Art von Darstellungsdiagramm befindet sich in "hyperopt.pyll", und wir nennen diese Diagramme "Pyll" -Diagramme oder "Pyll-Programme".

Falls gewünscht, kann der Probenraum abgetastet und ausgewertet werden.

import hyperopt.pyll.stochastic
print hyperopt.pyll.stochastic.sample(space)

Dieser Suchraum, der durch "Leerzeichen" beschrieben wird, hat drei Parameter:

Hierbei ist zu beachten, dass alle optimierbaren probabilistischen Ausdrücke als erstes Argument ein * label * haben. Diese Bezeichnungen werden verwendet, um Parameterauswahl an den Aufrufer zurückzugeben, und werden intern auf verschiedene Arten verwendet.

Eine andere Sache, die zu beachten ist, ist die Verwendung von Taples in der Mitte des Diagramms (um jeden von "Fall 1" und "Fall 2"). Listen, Wörterbücher und Tapples werden zu "deterministischen funktionalen Ausdrücken" aktualisiert und werden Teil des stochastischen Programms für den Suchraum.

Der dritte bemerkenswerte ist der numerische Ausdruck "1 + hp.lognormal (" c1 ", 0, 1)", der in die Beschreibung des Suchraums eingebettet ist. Was den Optimierungsalgorithmus betrifft, gibt es keinen Unterschied darin, 1 direkt zum Suchraum und 1 in der Logik der Zielfunktion selbst hinzuzufügen. Designer können wählen, wo eine solche Verarbeitung platziert werden soll, um die Art von Modularität zu erreichen, die sie benötigen. Das Ergebnis eines Zwischenausdrucks im Suchraum kann ein beliebiges Python-Objekt sein, auch wenn es parallel mit Mongodb optimiert wurde. Es ist einfach, der Beschreibung des Suchraums eine neue Art von nicht-probabilistischer Darstellung hinzuzufügen (siehe Abschnitt 2.3 unten).

Viertens sind 'c1'und'c2' Beispiele, die als bedingte Parameter bezeichnet werden. Jedes von 'c1' und 'c2' zeigt nur die Zahlen in der Stichprobe, die für einen bestimmten Wert von 'a' zurückgegeben wurden. Wenn 'a'is 0 ist, wird' c1 'verwendet, aber' c2 'wird nicht verwendet. Wenn 'a'is 1 ist, wird' c2 'verwendet, aber' c1 'wird nicht verwendet. Wenn es sinnvoll ist, sollten Sie die Parameter auf diese Weise als bedingt codieren, anstatt die Parameter in der Zielfunktion einfach zu ignorieren. Sie können effizienter suchen, wenn Sie feststellen, dass 'c1' die Zielfunktion möglicherweise nicht beeinflusst (da dies die Argumente der Zielfunktion nicht beeinflusst).

2.1 Parameterausdruck

Die derzeit vom Optimierungsalgorithmus von hyperopt erkannten Wahrscheinlichkeitsformeln sind:

2.2 A Search Space Example: scikit-learn

Um all diese Möglichkeiten in Aktion zu sehen, sehen wir uns an, wie scikit-learn die Hyperparameterräume des Klassifizierungsalgorithmus beschreibt. (Diese Idee wurde unter hyperopt-sklearn entwickelt.)

from hyperopt import hp
space = hp.choice('classifier_type', [
    {
        'type': 'naive_bayes',
    },
    {
        'type': 'svm',
        'C': hp.lognormal('svm_C', 0, 1),
        'kernel': hp.choice('svm_kernel', [
            {'ktype': 'linear'},
            {'ktype': 'RBF', 'width': hp.lognormal('svm_rbf_width', 0, 1)},
            ]),
    },
    {
        'type': 'dtree',
        'criterion': hp.choice('dtree_criterion', ['gini', 'entropy']),
        'max_depth': hp.choice('dtree_max_depth',
            [None, hp.qlognormal('dtree_max_depth_int', 3, 1, 1)]),
        'min_samples_split': hp.qlognormal('dtree_min_samples_split', 2, 1, 1),
    },
    ])

2.3 Hinzufügen nicht-probabilistischer Ausdrücke mit pyll

Sie können Knoten wie Argumente für die Pyll-Funktion verwenden (siehe Pyll). Wenn Sie mehr darüber erfahren möchten, reichen Sie bitte ein Github-Problem ein.

Einfach ausgedrückt, dekorieren Sie einfach die Funktionen der obersten Ebene (dh pickelfreundlich) für die Verwendung durch das Objekt "scope".

import hyperopt.pyll
from hyperopt.pyll import scope

@scope.define
def foo(a, b=0):
     print 'runing foo', a, b
     return a + b / 2

# -- this will print 0, foo is called as usual.
print foo(0)

#In der Beschreibung des Suchraums, wie bei normalem Python`foo`Kann verwendet werden.
#Diese beiden Anrufe nennen eigentlich nicht foo,
#Notieren Sie nur, dass Sie foo aufrufen müssen, um das Diagramm auszuwerten.

space1 = scope.foo(hp.uniform('a', 0, 10))
space2 = scope.foo(hp.uniform('a', 0, 10), hp.normal('b', 0, 1))

# -- this will print an pyll.Apply node
print space1

# -- this will draw a sample by running foo()
print hyperopt.pyll.stochastic.sample(space1)

2.4 Hinzufügen neuer Arten von Hyperparametern

Wenn möglich, sollte das Hinzufügen neuer Arten probabilistischer Darstellungen zur Beschreibung des Parametersuchraums vermieden werden. Damit alle Suchalgorithmen in allen Räumen funktionieren, müssen die Suchalgorithmen mit dem Typ des Hyperparameters übereinstimmen, der den Raum beschreibt. Als Bibliotheksbetreuer eröffne ich die Möglichkeit, dass von Zeit zu Zeit eine Art Ausdruck hinzugefügt werden sollte, aber wie gesagt, ich möchte dies so weit wie möglich vermeiden. Das Hinzufügen einer neuen Art von probabilistischer Darstellung ist keine der Möglichkeiten, wie Hyperopt erweiterbar ist.


Copyright (c) 2013, James Bergstra All rights reserved.

Recommended Posts

[Übersetzung] Hyperopt-Tutorial
Streamlit Tutorial Japanische Übersetzung
[Übersetzung] scicit-learn 0.18 Tutorial Manipulation von Textdaten
Biopython Tutorial und Kochbuch Japanische Übersetzung (4.3)
[Übersetzung] scikit-learn 0.18 Tutorial Inhaltsverzeichnis
Biopython Tutorial und Kochbuch Japanische Übersetzung (4.1)
Biopython Tutorial und Kochbuch Japanische Übersetzung (4.8)
Biopython Tutorial und Kochbuch Japanische Übersetzung (4.7)
Biopython Tutorial und Kochbuch Japanische Übersetzung (4.9)
Biopython Tutorial und Kochbuch Japanische Übersetzung (4.6)
Biopython Tutorial und Kochbuch Japanische Übersetzung (4.2)
Biopython Tutorial und Kochbuch Japanische Übersetzung (4.4)
sqlalchemy Tutorial
PyODE Tutorial 2
Python-Tutorial
PyODE Tutorial 1
PyODE Tutorial 3
Biopython Tutorial und Kochbuch Japanische Übersetzung (Kapitel 1, 2)
TensorFlow Tutorial Tutorial