Einordnung
Optimierungen sind in der modernen, digitalen Welt ein wichtiges Werkzeug geworden. In vielen Situationen sind Performanceerhöhungen wichtig - ob im privaten oder unternehmerischen Bereich. Vor allem die Anzahl der Parameter der immer komplexer werdenden Modellen macht eine händische oder analytische Optimierung immer komplexer. Entsprechend werde ich heute eine kurze Einführung in den Bereich der klassischen Optimierung in Python geben.
Grundlagen
Was ist das Ziel einer klassischen Optimierung?
Ziel einer Optimierung ist es, den Zielwert eines gegeben Modelles zu maximieren oder minimieren. Dies geschieht durch Variation verschiedener Parameter, welche im Modell definiert sind. Der Zielwert entsteht klassischerweise aus einer Zielfunktion, welche nicht unbedingt vorher bekannt sein muss. Anschließend können verschiedene Methoden verwendet werden, um sich langsam dem geforderten Optimum zu nähern. 1
Eine Liste verschiedener numerischer Verfahren, welche für eine solche Aufgabe verwendet werden können, können hier gefunden werden.
Abhängig von dem gegeben Problem, kann es sein das bestimmte Algorithmen keine Lösung finden können. Für verschiedene Probleme kann es sogar sein, dass keine Lösung - unabhängig von dem verwendeten Algorithmus - gefunden werden kann.
Implementierung eines Beispiels der klassischen Optimierung
Im Folgenden zeige ich nun ein Beispiel, wie eine Implementierung eines einfachen Beispiels aussehen könnte. Verwendet wird hierbei die Python-Library Optuna, welche eine Vereinfachung der Implementierung darstellt. Algorithmen zur Optimierung müssen hierbei nicht direkt selbst implementiert werden, sondern werden hierbei zur Verfügung gestellt. Eine effiziente Implementierung ist hierbei relevant, da hierdurch eine schnelle und effiziente Optimierung möglich gemacht wird. Diese effiziente Implementierung wird durch Optuna zur Verfügung gestellt.
Zusätzlich zeichnet sich Optuna durch die Kombatibilität mit allen aktuellen “Machine Learning”-Bibliotheken. Dies wird in einem anderen Artikel noch einmal betrachtet.
Einfaches Beispiel zum Einstieg
Zum Einstieg verwenden wir eine klassische Minimierungsaufgabe einer Funktion, in diesem Fall verwenden wir die Funktion
Die Funktion kann wie folgt im Intervall visualisiert werden:
Analytisch ist das Minimum simpel zu berechnen:
unter der Bedingung, dass Das Minimum liegt hierbei bei , da dort gilt.
Die Implementierung läuft wie folgt:
import optuna
def value(x):
return (4*(x**4) - 2*(x**2) + 7)
def objective(trial: optuna.trial.Trial):
x = trial.suggest_float("x", -4, 4)
return value(x)
study = optuna.create_study(study_name="Polynomial Example", direction="minimize")
max_trials = 250
study.optimize(objective, n_trials=max_trials)
Wichtig für Optuna ist die objective
-Funktion im Code. Diese gibt einen skalaren Wert zurück, bei welchem bestimmt werden kann, ob dieser maximiert oder minimiert werden
soll. Weiterhin wird dieser ein optuna.Trial.trial
-Objekt übergeben, durch welches alle Hyperparameter des aktuellen Optimierungsschrittes angefordert werden können. Dies
geschieht durch Funktionen wie trial.suggest_float
, welche den Namen des Parameters als Argument nehmen, sowie die obere und untere Grenze des Parameters. Für weitere
Funktionen zur Optimierung, siehe hier.
In dem Fall oben wird der Wert des Polynoms an der Stelle (welcher der Optimierungsparameter ist) zurückgegeben. Durch Ausführung des Codes beginnt Optuna sein Werk und minimiert den Funktionswert durch Anpassung unseres Parameters . Die Grenzen für den Parameter wurden als festgelegt. Nach Beendigung sollte ein Wert herauskommen.
Für größere Projekte bietet es sich an dieser Stelle an, den besten Wert und die Werte der besten Parametervariationen auszulesen. Dies kann wie folgt geschehen:
trial = study.best_trial
print("Best value: ", trial.value)
for key, param in trial.params.items():
print(f"{key}: {param}")
Eine Beispielausgabe sieht dann in dem oberen Beispiel so aus:
Best value: 6.750018072628766
x: 0.4978698668063428
In der nachfolgenden Grafik sind die entsprechenden Punkte angetragen, welche in der Optimierung verwendet wurden:
TL;DR
Optimierungsbibliotheken wie Optuna eignen sich hervoragend dazu, nicht nur Hyperparameteroptimierungen an neuronalen Netzen vorzunehmen, sondern auch klassischere, alltäglichere Optimierungsaufgaben durchzuführen. Hierfür sind keine großen Vorkenntnisse notwendig, sondern lediglich Daten des Optimierungsproblems notwendig. Durch seine Stabilität und Einfachheit in der Anwendung eignet sich in meinen Augen gerade Optuna sehr gut. Sollte Optuna aus einem bestimmten Grund nicht für die eigene Anwendung optimal sein, so kann auf eine Vielzahl anderer Optimierungsbibliotheken wie beispielsweise SciPy Optimize oder eine Reihe anderer Bibliotheken zurückgegriffen werden.
Viele Bibliotheken können hier verglichen werden.