Hallo alle zusammen!Dies ist der dritte Artikel darüber, wie ich einen kleinen und komfortablen Service mache, der theoretisch bei der Reiseplanung helfen sollte. In diesem Artikel werde ich darüber sprechen, wie der Flugpreis mit Clickhouse-, Catboost- und 1 TB * -Daten vorhergesagt werden kann.
Wofür ist das?
Eines der Hauptmerkmale von cheapster.travel ist die flexible Kombination komplexer Routen (mehr im vorherigen Artikel ). Um "All-with-All" zu kombinieren, wird ein Aggregator-Cache verwendet, in dem nicht immer Tickets gesucht werden, nach denen selten gesucht wird, und es ihnen schmerzlich fehlt, komplexe Routen zu erstellen. Jene. heiße Tickets (billig), auf denen komplexe Routen basieren , aber nicht genug 1-2 Segmente der "normalen" Tickets (zum regulären Preis, nicht in der beliebtesten Richtung). Es war dieses Problem, das mich dazu brachte, ein Modell zu bauen, das den Flugpreis vorhersagen konnte.Aufgabenformalisierung
- Sie müssen in der Lage sein, Tickets für Direktflüge vorherzusagen (nur Hin- und Rückflug).
- Sie müssen dies regelmäßig vorhersagen und in der Datenbank speichern können (einfaches Szenario).
- Müssen in der Lage sein, "on the fly" vorherzusagen (komplexes Szenario)
- Dies alles geschieht auf einer sehr begrenzten Hardware - daher ein Minimum an Manipulation mit großen Datenmengen
Wie kann man das machen?
Zunächst trainieren wir das Modell: Bereiten Sie das Dataset vor, markieren Sie die maximale Anzahl von Features in den Spalten, laden Sie es auf tsv hoch, laden Sie es in den DataFrame / Pool, analysieren Sie, wählen Sie die Parameter aus ... Stop, wir haben zu viele Daten und sie passen nicht in den Speicher , - folgende Fehler abfangen:MemoryError: Unable to allocate array with shape (38, 288224989) and data type float64
OSError: [Errno 12] Cannot allocate memory
Um diese Einschränkung zu umgehen, musste iterativ in kleinen Stücken gelernt werden. Es sieht folgendermaßen aus:model = CatBoostRegressor(cat_features=cat_features,
iterations=100,
learning_rate=.5,
depth=10,
l2_leaf_reg=9,
one_hot_max_size=5000)
for df in tqdm(pd.read_csv('history.tsv', sep='\t',
na_values=['\\N'],
chunksize=2_000_000)):
...
model.fit(X=df[df.columns[:-1]][:train_size].values,
y=df['price'][:train_size].values,
eval_set=eval_pool,
verbose=False,
plot=False,
init_model=model)
Das Ergebnis war ein Modell mit RMSE ~ 100 - im Allgemeinen wäre ich mit einem solchen Ergebnis zufrieden gewesen , aber nach einer kleinen Analyse und "Normalisierung" der Vorhersagen (Negative und Werte, die sich stark von den Min / Max-Werten in der Geschichte unterscheiden, werden an die entsprechenden Grenzen der historischen Preise gebracht). . Danach beträgt die Zielmetrik ~ 80, unter Berücksichtigung der Tatsache, dass es meiner Erfahrung nach fast keine Logik und keinen gesunden Menschenverstand bei der Preisgestaltung von Flugtickets gibt.Funktionen, die den Preis am meisten beeinflussen:
Statistiken für Funktionen „Entfernung zwischen Städten“:
Großartig, wir haben ein Modell - jetzt ist es Zeit, es zu verwenden. Fügen Sie zunächst das KX-Modell hinzu. Dies erfolgt mit einer einfachen Konfiguration:Konfig<models>
<model>
<type>catboost</type>
<name>price</name>
<path>/opt/models/price_iter_model_2.bin</path>
<lifetime>0</lifetime>
</model>
</models>
Wir führen einen regelmäßigen Vorhersageprozess durch - es ist einfach genug, dies mit Apache Airflow zu tun.Die resultierende DAG sieht so aus
DAGa ( Airflow):
SimpleHttpOperatorinsert_ow_in_tmp = SimpleHttpOperator(
task_id='insert_ow_in_tmp',
http_conn_id='clickhouse_http',
endpoint=dll_endpoint,
method='POST',
data=sql_templates.INSERT_OW_PREDICTIONS_IN_TMP,
pool='clickhouse_select',
dag=dag
)
Für die Vorhersage "on the fly" mit gewöhnlichem SQL:select origin, destination, date,
modelEvaluate('price', *) predicted_price
from log.history
+
| origin | destination | date | predicted_price |
+
| VKO | DEB | 2020-03-20 | 3234.43244 |
+
Ich möchte die Tatsache ersetzen, dass dieser Ansatz gewählt wurde, nicht nur, weil er einfacher zu implementieren ist - es gibt immer noch Pluspunkte:- Es ist nicht erforderlich, Daten außerhalb des KH hochzuladen (dies bedeutet eine schnellere und kostengünstigere Belastung des Bügeleisens).
- Keine Notwendigkeit, etl-Prozesse durchzuführen (einfacher = zuverlässiger)
Wir korrigieren die API und das Front-End leicht und erhalten die lang erwarteten Vorhersagen.Diese Vorhersagen passen auch gut in den Abschnitt Preisentwicklung für Flugtickets: Die
Funktionalität ist unter cheapster.travel/history verfügbar (sie wird auf dem Handy schief geöffnet, nur auf großen Bildschirmen).Das ist alles ein produktiver Tag!Vorherige Artikel
Ein Versuch, das Problem der Auswahl von Flugtickets vor dem Urlaub zu lösen Ein Versuch, das Problem der Auswahl von Flugtickets vor dem Urlaubzu lösen # 2Ein weiteres interessantes Feature
Kombinator schwieriger RoutenKomplexe Tickets (Dreiecke)PSWichtig! Nehmen Sie diese Vorhersagen nicht als etwas, das Ihnen bei der Auswahl eines Kaufdatums hilft - das Modell kann möglicherweise nicht richtig vorhersagen, außerdem wurde seine Angemessenheit weder von mir noch von anderen überprüft (alles auf eigene Gefahr und Gefahr, ohne Garantien).1 TB * - Dies ist, wenn Sie auf tsv hochladen, in KX dauert es eine Größenordnung weniger.UPD:Die wichtigsten nicht offensichtlichen Probleme bei der Verwendung von Catboost-Bundles - Clickhouse
- Kategoriale Merkmale in KH ändern die Reihenfolge und werden am Ende (und nicht in der Reihenfolge, die während des Trainings war);
- modelEvaluate gibt null zurück - Sie müssen überprüfen, ob Sie Nullwerte in Features haben, wenn Sie diese durch nan ersetzen müssen
- In dem neuen Versionen gibt es einen nicht offensichtlichen Moment mit dem Config - Format für KX, beschrieben hier