Nachdem alle Parameter festgelegt und in der Datenbank gespeichert wurden, kann die Auswahl des passenden Modells erfolgen. Hierbei fließen aber nicht nur rein mathematische Aspekte ein.
Damit einher geht ein umfassendes Parameter-Tuning.
Für die PV-Ertragsprognose bieten sich für diesen Anwendungsfall i.W. zwei Modell-Ansätze an:
Das kann man so pauschal nicht sagen.
Ich hatte eine Vielzahl von Modellen und Ansätzen mit den verschiedensten Parametern und Modellkoeffizienten getestet. Mit einem LSTM erreichte ich eine Passgenauigkeit von knapp 94%, mit dem besten Entscheidungsbaum kam ich ebenfalls auf ca. 94%. Doch letztendlich haben andere Randbedingungen den Ausschlag gegeben.
Wie bereits zu Beginn dieser Serie erwähnt, muss das Modell auf einer Hardware laufen, die 24/7 am Netz ist. Daraus resultierend bleibt nur mein Raspberry PI 2, den ich für mein Smart Home verwende oder mein Synology NAS-Server. Mein Respberry hat nicht die Ressourcen, um komplexe Modelle zu hosten - mein NAS-Server hätte diese Ressourcen hingegen schon. Allerdings barg mein NAS-Server ganz andere Probleme in sich.
Für das LSTM-Modell verwendete ich als Framework Tensorflow. Das benötigt grundsätzlich sehr viele Ressourcen. Es gibt auch Tensorflow light (Runtime-Modul), mit dem man auf anderer Hardware trainierte Modelle für die Vorhersage laufen lassen kann. Bei meinem LSTM-Model waren aber zusätzliche Flex-Delegations notwendig, die im Standard Tensorflow light oder LiteRT, wie es jetzt heißt, nicht enthalten sind.
Somit war mein Ziel, ein individuelles Tensorflow light mit Flex-Delegations zu kompilieren, insbesondere mit den fehlenden select_tf_ops. Hierzu fand ich leider in der Anleitung den Hinweis, dass dies nicht möglich ist, sofern man als Ergebnis ein Wheel-File benötigt. Ich hatte es trotzdem probiert. Es gelang mir nicht. Somit schied diese Version aus.
Mein NAS-Server würde auch die Ressourcen für das komplette Tensorflow Framework aufbringen. Doch leider läuft hier das Framework ebenfalls nicht, da mein NAS einen Intel Celeron Prozessor beinhaltet und bei diesem Prozessor die AVX Unterstützung fehlt. Das individuelle Kompilieren des gesamten Tensorflow Framework ohne AVX Unterstützung hätte die Hardware-Ressourcen auf meinem NAS dann doch überfordert.
Insofern blieben Entscheidungsbäume (Regressoren) als Option. Da die Genauigkeit der beiden Ansätze ähnlich ist, habe ich kein Problem damit. Ich sehe es also nicht als zweitbeste Lösung, sondern als eine Lösung.
Um den passenden Regressionsansatz zu finden, bietet es sich an, mit Hilfe der Pipeline-Funktionalität von Scikit-learn das Modell mit unterschiedlichen Regressoren zu berechnen. Hier ist ein gutes Beispiel dafür. In meinem Anwendungsfall hat die Berechnung ergeben, dass der Random Forest Regressor die besten Ergebnisse liefert (basierend auf dem R2-Score). Ein Random Forest besteht vereinfacht gesagt aus einer Kombination von vielen kleinen Entscheidungsbäumen.
Kategorische Daten beinhalten Informationen, die nicht nur ihrem numerischen Werten entsprechen. Typisches Beispiel ist das Geschlecht: männlich / weiblich. Solche alphanumerischen Begrifflichkeiten können Machine-Learning Modelle meist nicht verwerten, weshalb sie in ein numerisches Äquivalent umcodiert werden müssen. Hier z.B. männlich = 1 / weiblich = 2. Danach kann dieses Merkmal z.B. für Gruppierungen verwendet werden.
In diesem konkreten Modell gibt es keine alphanumerischen Daten. Trotzdem erscheint eine Kategorisierung als sinnvoll. Der Monat ist hierfür ein guter Kandidat. Wenn man nicht möchte, dass die Daten des Januars mit den Daten des Juni gleichbehandelt werden, dann ist es naheliegend, die Monate saisonal zu gruppieren. Es bieten sich drei Gruppierungen (Saisonabschnitte) an:
Das konkrete Mapping sieht wie folgt aus:
month_seasson_mapping = {
1:1, 2:1, 3:2, 4:2, 5:3, 6:3, 7:3, 8:3, 9:2, 10:2, 11:1, 12:1
}
data["Seasson"] = data["Month"].map(lambda x: month_seasson_mapping[x])
categorical_features = pd.get_dummies(data, columns = ['Seasson'])
Mit der Festlegung auf einen Random Forest Regressor und der Berücksichtigung von saisonalen Effekten ist die Optimierung noch nicht abgeschlossen. Jetzt geht es an das Fine Tuning oder besser gesagt, an das Hyperparameter Tuning. Jeder Modellansatz hat eine Vielzahl von Parametern oder Modellkoeffizienten. Das Ziel dieser Optimierung ist es, die optimalen Werte dieser Parameter zu finden, z.B.:
Beim Hyperparameter Tuning stehen zwei Ansätze im Mittelpunkt:
Für beide Ansätze gilt, dass in jedem Fall eine Baseline-Berechnung erfolgen muss, damit am Ende ein Vergleichswert zur Verfügung steht, an dem sich die Verbesserung des Modells messen lässt.
Nachdem alle Optimierungsschritte durchlaufen wurden, können die ermittelten Parameter in das eigentliche Modell übernommen und das erste Training durchgeführt werden. Die Datenaufteilung erfolgte bei 75% für Train und 25% für Test, wobei ein Augenmerk darauf lag, den Splitt nicht innerhalb eines Tages zu vollziehen. Es gibt als auf Train- und Test-Seite immer nur ganze Tage. Das trainierte Modell kann im pickle Format (.pkl) abgespeichert werden.
Die Vorhersage erfordert deutlich weniger Rechenleistung, als das Modell Training. Insofern kann das abgespeicherte Modell auch auf schwächere Hardware übertragen werden, die andere Vorteile haben kann, wie z.B. einen 24/7 Betrieb.
Für die Übertragung des Modell auf eine schwächere Hardware ist es sinnvoll, den Code hinsichtlich der verwendeten Libraries (Ressourcen) zu optimieren. So habe ich in der optimierten Version Pandas durch Numpy ersetzt. Der Schritt ging einher mit der Vereinigung der kaskadierende Vorhersage (Brightness / Energy) in ein gemeinsames Script. So sind jetzt für eine PV-Ertragsvorhersage nicht mehr zwei getrennte Scriptaufrufe notwendig, sondern die Berechnung erfolgt in einem Script mit zwei Schleifendurchläufen. An der Programmlogik hat sich dadurch nichts geändert.
Die Vorhersageergebnisse werden wiederum über stored Prcedures in die Datenbank geschrieben und zusätzlich über das MQTT-Protokoll an FHEM übertragen. In der Datenbank sind hierfür separate Datenfelder vorgesehen (BrightnessFc und EnergyHourFc). Somit können später die Vorhersagewerte mit den historischen Ist-Werten weiterhin verglichen werden.
Jupyter Notebook für den kaskadierenden Zwischenschritt „Vorhersage der Helligkeit“:
Darauf aufbauend die eigentliche PV-Ertragsprognose:
Das daraus resultierende Python-Script, welches produktiv verwendet wird:
Stored Procedures, mit denen die Vorhersageergebnisse in die Datenbank geschrieben werden:
Fragen oder Anregungen nehme ich gern über die Kontaktbox entgegen oder direkt per Email.
kontakt@kaempf-nk.de