SNA Hackathon 2019

Im Februar und März 2019 fand ein Wettbewerb zur Bewertung des Feeds des sozialen Netzwerks statt SNA Hackathon 2019, bei dem unser Team den ersten Platz belegte. In dem Artikel werde ich über die Organisation des Wettbewerbs, die von uns ausprobierten Methoden und die Catboost-Einstellungen für das Training mit Big Data sprechen.

SNA Hackathon 2019

SNA-Hackathon

Es ist bereits das dritte Mal, dass ein Hackathon unter diesem Namen stattfindet. Es wird vom sozialen Netzwerk ok.ru organisiert bzw. die Aufgabe und Daten stehen in direktem Zusammenhang mit diesem sozialen Netzwerk.
SNA (Social Network Analysis) wird in diesem Fall korrekter nicht als Analyse eines sozialen Diagramms, sondern als Analyse eines sozialen Netzwerks verstanden.

  • Im Jahr 2014 bestand die Aufgabe darin, vorherzusagen, wie viele Likes ein Beitrag erhalten würde.
  • Im Jahr 2016 - die VVZ-Aufgabe (vielleicht kennen Sie das), näher an der Analyse des Sozialgraphen.
  • Im Jahr 2019 wird der Feed des Benutzers anhand der Wahrscheinlichkeit bewertet, dass der Beitrag dem Benutzer gefällt.

Über 2014 kann ich nichts sagen, aber in den Jahren 2016 und 2019 waren neben Datenanalysefähigkeiten auch Kenntnisse im Umgang mit Big Data gefragt. Ich denke, es war die Kombination aus maschinellem Lernen und Big-Data-Verarbeitungsproblemen, die mich zu diesen Wettbewerben hingezogen hat, und meine Erfahrung in diesen Bereichen hat mir zum Sieg verholfen.

mlbootcamp

Im Jahr 2019 wurde der Wettbewerb auf der Plattform organisiert https://mlbootcamp.ru.

Der Wettbewerb begann online am 7. Februar und bestand aus 3 Aufgaben. Jeder konnte sich auf der Website registrieren und herunterladen Baseline und beladen Sie Ihr Auto für ein paar Stunden. Am Ende der Online-Phase am 15. März wurden die Top 15 jeder Springveranstaltung in das Mail.ru-Büro zur Offline-Phase eingeladen, die vom 30. März bis 1. April stattfand.

Aufgabe

Die Quelldaten stellen Benutzer-IDs (userId) und Beitrags-IDs (objectId) bereit. Wenn dem Benutzer ein Beitrag angezeigt wurde, enthalten die Daten eine Zeile mit Benutzer-ID, Objekt-ID, Benutzerreaktionen auf diesen Beitrag (Feedback) und einer Reihe verschiedener Funktionen oder Links zu Bildern und Texten.

Benutzeridentifikation Objekt Identifikation Eigentümer-ID Feedback Bilder
3555 22 5677 [Gefällt mir, angeklickt] [Hash1]
12842 55 32144 [nicht gefallen] [Hash2,Hash3]
13145 35 5677 [geklickt, geteilt] [Hash2]

Der Testdatensatz enthält eine ähnliche Struktur, jedoch fehlt das Feedback-Feld. Die Aufgabe besteht darin, das Vorhandensein der „Gefällt mir“-Reaktion im Feedbackfeld vorherzusagen.
Die Einreichungsdatei hat folgenden Aufbau:

Benutzeridentifikation SortedList[objectId]
123 78,13,54,22
128 35,61,55
131 35,68,129,11

Die Metrik ist die durchschnittliche ROC-AUC für Benutzer.

Eine detailliertere Beschreibung der Daten finden Sie unter Website des Gemeinderats. Dort können Sie auch Daten inklusive Tests und Bilder herunterladen.

Online-Bühne

In der Online-Phase wurde die Aufgabe in drei Teile unterteilt

Offline-Bühne

In der Offline-Phase umfassten die Daten alle Funktionen, während Texte und Bilder spärlich waren. Der Datensatz enthielt 1,5-mal mehr Zeilen, von denen es bereits viele gab.

Problemlösung

Da ich bei der Arbeit einen Lebenslauf verfasse, habe ich meine Reise in diesen Wettbewerb mit der Aufgabe „Bilder“ begonnen. Die bereitgestellten Daten waren Benutzer-ID, Objekt-ID, Eigentümer-ID (die Gruppe, in der der Beitrag veröffentlicht wurde), Zeitstempel für die Erstellung und Anzeige des Beitrags und natürlich das Bild für diesen Beitrag.
Nachdem mehrere Features auf der Grundlage von Zeitstempeln generiert wurden, bestand die nächste Idee darin, die vorletzte Schicht des auf Imagenet vorab trainierten Neurons zu nehmen und diese Einbettungen zum Boosten zu senden.

SNA Hackathon 2019

Die Ergebnisse waren nicht beeindruckend. Einbettungen aus dem Imagenet-Neuron sind irrelevant, ich dachte, ich muss meinen eigenen Autoencoder erstellen.

SNA Hackathon 2019

Es hat viel Zeit gekostet und das Ergebnis hat sich nicht verbessert.

Feature-Generierung

Da die Arbeit mit Bildern viel Zeit in Anspruch nimmt, habe ich mich für etwas Einfacheres entschieden.
Wie Sie sofort erkennen können, enthält der Datensatz mehrere kategoriale Merkmale. Um mich nicht zu sehr darum zu kümmern, habe ich einfach Catboost verwendet. Die Lösung war hervorragend, ohne irgendwelche Einstellungen gelangte ich sofort in die erste Zeile der Bestenliste.

Es gibt ziemlich viele Daten und sie sind im Parkettformat angelegt, also nahm ich ohne lange nachzudenken, nahm ich Scala und begann, alles in Spark zu schreiben.

Die einfachsten Funktionen, die mehr Wachstum brachten als Bilderinbettungen:

  • Wie oft erschienen Objekt-ID, Benutzer-ID und Eigentümer-ID in den Daten (sollte mit der Beliebtheit korrelieren);
  • Wie viele Beiträge hat Benutzer-ID von Eigentümer-ID gesehen (sollte mit dem Interesse des Benutzers an der Gruppe korrelieren);
  • wie viele eindeutige Benutzer-IDs Beiträge von Eigentümer-ID angesehen haben (spiegelt die Größe der Zielgruppe der Gruppe wider).

Aus Zeitstempeln konnte die Tageszeit ermittelt werden, zu der der Nutzer den Feed angeschaut hat (morgens/nachmittags/abends/nachts). Durch die Kombination dieser Kategorien können Sie weiterhin Funktionen generieren:

  • Wie oft hat sich Benutzer-ID abends angemeldet?
  • zu welcher Zeit dieser Beitrag am häufigsten angezeigt wird (objectId) und so weiter.

All dies verbesserte nach und nach die Kennzahlen. Da der Trainingsdatensatz jedoch etwa 20 Millionen Datensätze umfasst, wurde das Training durch das Hinzufügen von Funktionen erheblich verlangsamt.

Ich habe meinen Ansatz zur Nutzung von Daten überdacht. Obwohl die Daten zeitabhängig sind, habe ich keine offensichtlichen Informationslecks „in der Zukunft“ gesehen, dennoch habe ich sie für alle Fälle wie folgt aufgeschlüsselt:

SNA Hackathon 2019

Das uns zur Verfügung gestellte Schulungsset (Februar und 2 Wochen im März) war in 2 Teile unterteilt.
Das Modell wurde auf Daten der letzten N Tage trainiert. Die oben beschriebenen Aggregationen wurden auf allen Daten, einschließlich des Tests, erstellt. Gleichzeitig sind Daten aufgetaucht, auf denen verschiedene Kodierungen der Zielvariablen aufgebaut werden können. Der einfachste Ansatz besteht darin, Code wiederzuverwenden, der bereits neue Funktionen erstellt, und ihm einfach Daten zuzuführen, auf denen er nicht trainiert wird, und das Ziel = 1.

Somit haben wir ähnliche Funktionen erhalten:

  • Wie oft hat Benutzer-ID einen Beitrag in der Gruppe Eigentümer-ID gesehen?
  • Wie oft hat Benutzer-ID den Beitrag in der Gruppe „OwnerId“ mit „Gefällt mir“ markiert?
  • Der Prozentsatz der Beiträge, die Benutzer-ID von Eigentümer-ID mit „Gefällt mir“ markiert hat.

Das heißt, es stellte sich heraus mittlere Zielkodierung auf einen Teil des Datensatzes für verschiedene Kombinationen kategorialer Merkmale. Im Prinzip baut catboost auch eine Zielkodierung auf und aus dieser Sicht gibt es keinen Nutzen, aber es wurde beispielsweise möglich, die Anzahl der eindeutigen Benutzer zu zählen, denen Beiträge in dieser Gruppe gefallen haben. Gleichzeitig wurde das Hauptziel erreicht – mein Datensatz wurde um ein Vielfaches reduziert und es war möglich, weiterhin Features zu generieren.

Während Catboost eine Kodierung nur auf der Grundlage der „Gefällt mir“-Reaktion erstellen kann, hat Feedback andere Reaktionen: erneut geteilt, nicht gemocht, nicht gemocht, angeklickt, ignoriert, Kodierungen, für die manuell vorgenommen werden kann. Ich habe alle Arten von Aggregaten neu berechnet und Features mit geringer Bedeutung eliminiert, um den Datensatz nicht aufzublähen.

Zu diesem Zeitpunkt lag ich mit großem Abstand auf dem ersten Platz. Das Einzige, was verwirrend war, war, dass Bildeinbettungen fast kein Wachstum zeigten. Es entstand die Idee, alles für catboost zu geben. Wir gruppieren Kmeans-Bilder und erhalten eine neue kategoriale Funktion imageCat.

Hier sind einige Klassen nach manueller Filterung und Zusammenführung von Clustern, die von KMeans erhalten wurden.

SNA Hackathon 2019

Basierend auf imageCat generieren wir:

  • Neue kategoriale Funktionen:
    • Welches BildCat wurde von userId am häufigsten angesehen;
    • Welches ImageCat zeigt am häufigsten die Eigentümer-ID an;
    • Welches imageCat wurde von userId am häufigsten geliked?
  • Verschiedene Zähler:
    • Wie viele eindeutige imageCat hat sich die Benutzer-ID angesehen?
    • Ungefähr 15 ähnliche Funktionen plus Zielkodierung wie oben beschrieben.

Texte

Die Ergebnisse des Bildwettbewerbs gefielen mir und ich beschloss, mich an Texten zu versuchen. Ich habe vorher nicht viel mit Texten gearbeitet und dummerweise habe ich den Tag mit tf-idf und svd totgeschlagen. Dann habe ich Baseline mit doc2vec gesehen, das genau das tut, was ich brauche. Nachdem ich die doc2vec-Parameter leicht angepasst hatte, erhielt ich Texteinbettungen.

Und dann habe ich einfach den Code für die Bilder wiederverwendet, indem ich die Bildeinbettungen durch Texteinbettungen ersetzt habe. Dadurch belegte ich beim Textwettbewerb den 2. Platz.

Kollaboratives System

Es gab noch einen Wettbewerb, den ich noch nicht mit einem Stock „gestochen“ hatte, und nach der AUC in der Bestenliste zu urteilen, dürften die Ergebnisse dieses speziellen Wettbewerbs den größten Einfluss auf die Offline-Phase gehabt haben.
Ich habe alle in den Quelldaten enthaltenen Merkmale genommen, kategoriale Merkmale ausgewählt und die gleichen Aggregate wie für Bilder berechnet, mit Ausnahme der Merkmale, die auf den Bildern selbst basieren. Allein das Einschalten von Catboost brachte mich auf den 2. Platz.

Erste Schritte der Catboost-Optimierung

Ein erster und zwei zweite Plätze freuten mich, aber man war sich darüber im Klaren, dass ich nichts Besonderes gemacht hatte, was bedeutete, dass ich mit einem Positionsverlust rechnen musste.

Die Aufgabe des Wettbewerbs besteht darin, Beiträge innerhalb des Benutzers zu bewerten, und die ganze Zeit über habe ich das Klassifizierungsproblem gelöst, also die falsche Metrik optimiert.

Ich werde ein einfaches Beispiel geben:

Benutzeridentifikation Objekt Identifikation Prognose Grund Wahrheit
1 10 0.9 1
1 11 0.8 1
1 12 0.7 1
1 13 0.6 1
1 14 0.5 0
2 15 0.4 0
2 16 0.3 1

Lassen Sie uns eine kleine Umstellung vornehmen

Benutzeridentifikation Objekt Identifikation Prognose Grund Wahrheit
1 10 0.9 1
1 11 0.8 1
1 12 0.7 1
1 13 0.6 0
2 16 0.5 1
2 15 0.4 0
1 14 0.3 1

Wir erhalten folgende Ergebnisse:

Modell AUC Benutzer1 AUC Benutzer2 AUC mittlere AUC
Option 1 0,8 1,0 0,0 0,5
Option 2 0,7 0,75 1,0 0,875

Wie Sie sehen, bedeutet die Verbesserung der gesamten AUC-Metrik nicht, dass die durchschnittliche AUC-Metrik innerhalb eines Benutzers verbessert wird.

Katboost weiß, wie man Ranking-Metriken optimiert aus der Schachtel. Ich habe über Ranking-Metriken gelesen, Erfolgsgeschichten bei Verwendung von Catboost und stellen Sie YetiRankPairwise so ein, dass es über Nacht trainiert. Das Ergebnis war nicht beeindruckend. Da ich entschied, dass ich nicht ausreichend trainiert war, änderte ich die Fehlerfunktion in QueryRMSE, was der Catboost-Dokumentation zufolge schneller konvergiert. Am Ende habe ich die gleichen Ergebnisse erzielt wie beim Klassifizierungstraining, die Ensembles dieser beiden Modelle lieferten jedoch eine gute Steigerung, die mir in allen drei Wettbewerben den ersten Platz einbrachte.

5 Minuten vor dem Ende der Online-Phase des Wettbewerbs „Kollaborative Systeme“ hat mich Sergey Shalnov auf den zweiten Platz verwiesen. Den weiteren Weg gingen wir gemeinsam.

Vorbereitung auf die Offline-Phase

Der Sieg in der Online-Phase war uns mit einer RTX 2080 TI-Grafikkarte garantiert, aber der Hauptpreis von 300 Rubel und höchstwahrscheinlich sogar der endgültige erste Platz zwangen uns, diese zwei Wochen zu arbeiten.

Wie sich herausstellte, nutzte Sergey auch Catboost. Wir haben Ideen und Features ausgetauscht und ich habe davon erfahren Bericht von Anna Veronica Dorogush das Antworten auf viele meiner Fragen enthielt, und sogar auf solche, die ich zu diesem Zeitpunkt noch nicht hatte.

Als ich mir den Bericht ansah, kam ich auf die Idee, dass wir alle Parameter auf die Standardwerte zurücksetzen und die Einstellungen sehr sorgfältig und erst nach der Korrektur einer Reihe von Funktionen vornehmen müssen. Nun dauerte ein Training etwa 15 Stunden, aber einem Modell gelang es, eine bessere Geschwindigkeit zu erreichen als im Ensemble mit Ranking.

Feature-Generierung

Im Wettbewerb „Kollaborative Systeme“ werden zahlreiche Merkmale als wichtig für das Modell bewertet. Zum Beispiel, auditweights_spark_svd - das wichtigste Zeichen, aber es gibt keine Informationen darüber, was es bedeutet. Ich dachte, es wäre lohnenswert, die verschiedenen Aggregate anhand wichtiger Merkmale zu zählen. Beispiel: Durchschnittliche auditweights_spark_svd nach Benutzer, nach Gruppe, nach Objekt. Das Gleiche kann anhand von Daten berechnet werden, für die kein Training durchgeführt wird und bei denen der Zielwert = 1, also der Durchschnitt, ist auditweights_spark_svd vom Benutzer nach Objekten, die ihm gefallen haben. Wichtige Zeichen außerdem auditweights_spark_svd, Da waren mehrere. Hier sind einige davon:

  • auditweightsCtrGender
  • auditweightsCtrHigh
  • userOwnerCounterCreateLikes

Zum Beispiel der Durchschnitt auditweightsCtrGender Laut userId erwies es sich als wichtiges Merkmal, genau wie der Durchschnittswert userOwnerCounterCreateLikes nach Benutzer-ID+Besitzer-ID. Das sollte Sie bereits denken lassen, dass Sie die Bedeutung der Felder verstehen müssen.

Wichtige Features waren auch auditweightsLikesCount и auditweightsShowsCount. Durch die Division durcheinander erhielt man ein noch wichtigeres Merkmal.

Datenlecks

Wettbewerbs- und Produktionsmodellierung sind sehr unterschiedliche Aufgaben. Bei der Datenvorbereitung ist es sehr schwierig, alle Details zu berücksichtigen und nicht einige nicht triviale Informationen über die Zielvariable im Test zu vermitteln. Wenn wir eine Produktionslösung erstellen, werden wir versuchen, beim Training des Modells Datenlecks zu vermeiden. Aber wenn wir die Konkurrenz gewinnen wollen, dann sind Datenlecks die besten Eigenschaften.

Nachdem Sie die Daten untersucht haben, können Sie dies anhand der objectId-Werte erkennen auditweightsLikesCount и auditweightsShowsCount Dies bedeutet, dass das Verhältnis der Maximalwerte dieser Funktionen die Post-Konvertierung viel besser widerspiegelt als das Verhältnis zum Zeitpunkt der Anzeige.

Das erste Leck, das wir gefunden haben, ist auditweightsLikesCountMax/auditweightsShowsCountMax.
Was aber, wenn wir uns die Daten genauer ansehen? Sortieren wir nach Showdatum und erhalten Sie:

Objekt Identifikation Benutzeridentifikation auditweightsShowsCount auditweightsLikesCount Ziel (wird gemocht)
1 1 12 3 wahrscheinlich nicht
1 2 15 3 vielleicht ja
1 3 16 4

Es war überraschend, als ich das erste Beispiel dieser Art fand und sich herausstellte, dass meine Vorhersage nicht wahr wurde. Aber unter Berücksichtigung der Tatsache, dass die Maximalwerte dieser Eigenschaften innerhalb des Objekts zu einem Anstieg führten, waren wir nicht faul und beschlossen, etwas zu finden auditweightsShowsCountNext и auditweightsLikesCountNext, also die Werte zum nächsten Zeitpunkt. Durch Hinzufügen einer Funktion
(auditweightsShowsCountNext-auditweightsShowsCount)/(auditweightsLikesCount-auditweightsLikesCountNext) Wir machten schnell einen scharfen Sprung.
Ähnliche Lecks könnten genutzt werden, indem die folgenden Werte ermittelt werden userOwnerCounterCreateLikes innerhalb von userId+ownerId und zum Beispiel auditweightsCtrGender innerhalb von objectId+userGender. Wir haben 6 ähnliche Felder mit Lecks gefunden und daraus so viele Informationen wie möglich extrahiert.

Zu diesem Zeitpunkt hatten wir so viele Informationen wie möglich aus kollaborativen Funktionen herausgeholt, kehrten aber nicht zu Bild- und Textwettbewerben zurück. Ich hatte eine tolle Idee zu prüfen: Wie viel geben Features, die direkt auf Bildern oder Texten basieren, bei relevanten Wettbewerben?

Bei den Bild- und Textwettbewerben gab es keine Lecks, aber zu diesem Zeitpunkt hatte ich die Standard-Catboost-Parameter wiederhergestellt, den Code bereinigt und einige Funktionen hinzugefügt. Die Summe betrug:

Lösung bald
Maximal mit Bildern 0.6411
Maximal keine Bilder 0.6297
Ergebnis für den zweiten Platz 0.6295

Lösung bald
Maximal mit Texten 0.666
Maximal ohne Texte 0.660
Ergebnis für den zweiten Platz 0.656

Lösung bald
Maximale Zusammenarbeit 0.745
Ergebnis für den zweiten Platz 0.723

Es wurde klar, dass wir aus Texten und Bildern wahrscheinlich nicht viel herausholen würden, und nachdem wir einige der interessantesten Ideen ausprobiert hatten, hörten wir auf, damit zu arbeiten.

Die weitere Generierung von Funktionen in kollaborativen Systemen führte nicht zu einer Steigerung, und wir begannen mit der Rangfolge. Auf der Online-Stufe verschaffte mir das Klassifikations- und Ranking-Ensemble eine kleine Steigerung, wie sich herausstellte, weil ich die Klassifikation zu wenig trainiert hatte. Keine der Fehlerfunktionen, einschließlich YetiRanlPairwise, lieferte auch nur annähernd das Ergebnis von LogLoss (0,745 vs. 0,725). Es gab noch Hoffnung für QueryCrossEntropy, das nicht gestartet werden konnte.

Offline-Bühne

In der Offline-Phase blieb die Datenstruktur dieselbe, es gab jedoch geringfügige Änderungen:

  • Bezeichner userId, objectId,ownerId wurden neu randomisiert;
  • mehrere Schilder wurden entfernt und mehrere umbenannt;
  • Die Daten haben sich etwa um das 1,5-fache erhöht.

Zusätzlich zu den aufgeführten Schwierigkeiten gab es ein großes Plus: Dem Team wurde ein großer Server mit einer RTX 2080TI zugewiesen. Ich habe htop schon lange genossen.
SNA Hackathon 2019

Es gab nur eine Idee: einfach das zu reproduzieren, was bereits existiert. Nachdem wir einige Stunden damit verbracht hatten, die Umgebung auf dem Server einzurichten, begannen wir nach und nach zu überprüfen, ob die Ergebnisse reproduzierbar waren. Das Hauptproblem, mit dem wir konfrontiert sind, ist die Zunahme des Datenvolumens. Wir haben uns entschieden, die Last etwas zu reduzieren und den Catboost-Parameter ctr_complexity=1 zu setzen. Dadurch wird die Geschwindigkeit etwas verringert, aber mein Modell fing an zu arbeiten, das Ergebnis war gut – 0,733. Im Gegensatz zu mir hat Sergey die Daten nicht in zwei Teile aufgeteilt und mit allen Daten trainiert, obwohl dies in der Online-Phase die besten Ergebnisse lieferte, gab es in der Offline-Phase viele Schwierigkeiten. Wenn wir alle von uns generierten Funktionen nehmen und versuchen würden, sie in Catboost zu integrieren, würde in der Online-Phase nichts funktionieren. Sergey führte eine Typoptimierung durch, indem er beispielsweise float2-Typen in float64 konvertierte. In diesem Artikel, Informationen zur Speicheroptimierung finden Sie in Pandas. Als Ergebnis trainierte Sergey die CPU anhand aller Daten und erreichte etwa 0,735.

Diese Ergebnisse reichten zum Sieg, aber wir verheimlichten unsere wahre Geschwindigkeit und konnten nicht sicher sein, dass andere Teams nicht dasselbe taten.

Kämpfe bis zum Letzten

Catboost-Tuning

Unsere Lösung wurde vollständig reproduziert, wir haben die Funktionen von Textdaten und Bildern hinzugefügt, sodass nur noch die Catboost-Parameter abgestimmt werden mussten. Sergey trainierte auf der CPU mit einer kleinen Anzahl von Iterationen, und ich trainierte auf der CPU mit ctr_complexity=1. Es blieb nur noch ein Tag, und wenn Sie nur Iterationen hinzufügen oder ctr_complexity erhöhen würden, könnten Sie am Morgen eine noch bessere Geschwindigkeit erreichen und den ganzen Tag laufen.

In der Offline-Phase könnten Geschwindigkeiten sehr leicht ausgeblendet werden, indem einfach nicht die beste Lösung auf der Website ausgewählt wird. Wir erwarteten drastische Änderungen in der Bestenliste in den letzten Minuten vor Abschluss der Einreichungen und beschlossen, nicht damit aufzuhören.

Aus Annas Video habe ich gelernt, dass es am besten ist, die folgenden Parameter auszuwählen, um die Qualität des Modells zu verbessern:

  • Lernrate — Der Standardwert wird basierend auf der Größe des Datensatzes berechnet. Um die Lernrate zu erhöhen, muss die Anzahl der Iterationen erhöht werden.
  • l2_leaf_reg – Regularisierungskoeffizient, Standardwert 3, vorzugsweise 2 bis 30. Eine Verringerung des Werts führt zu einer Erhöhung der Überanpassung.
  • bagging_temperature – fügt den Gewichten der Objekte in der Stichprobe eine Randomisierung hinzu. Der Standardwert ist 1, wobei die Gewichtungen aus einer Exponentialverteilung stammen. Eine Verringerung des Werts führt zu einem Anstieg der Überanpassung.
  • random_strength – Beeinflusst die Auswahl der Aufteilungen bei einer bestimmten Iteration. Je höher die random_strength, desto höher ist die Wahrscheinlichkeit, dass eine Aufteilung mit geringer Wichtigkeit ausgewählt wird. Mit jeder weiteren Iteration nimmt die Zufälligkeit ab. Eine Verringerung des Werts führt zu einem Anstieg der Überanpassung.

Andere Parameter haben einen viel geringeren Einfluss auf das Endergebnis, daher habe ich nicht versucht, sie auszuwählen. Eine Trainingsiteration meines GPU-Datensatzes mit ctr_complexity=1 dauerte 20 Minuten, und die ausgewählten Parameter im reduzierten Datensatz unterschieden sich geringfügig von den optimalen Parametern im gesamten Datensatz. Am Ende habe ich etwa 30 Iterationen mit 10 % der Daten durchgeführt und dann etwa 10 weitere Iterationen mit allen Daten. Es stellte sich ungefähr so ​​heraus:

  • Lernrate Ich habe den Standardwert um 40 % erhöht;
  • l2_leaf_reg ließ es gleich;
  • bagging_temperature и random_strength auf 0,8 reduziert.

Wir können daraus schließen, dass das Modell mit den Standardparametern nicht ausreichend trainiert wurde.

Ich war sehr überrascht, als ich das Ergebnis auf der Bestenliste sah:

Modell 1-Modell 2-Modell 3-Modell Ensemble
Ohne Tuning 0.7403 0.7404 0.7404 0.7407
Mit Tuning 0.7406 0.7405 0.7406 0.7408

Ich bin zu dem Schluss gekommen, dass es besser ist, die Auswahl der Parameter durch ein Ensemble mehrerer Modelle mit nicht optimierten Parametern zu ersetzen, wenn eine schnelle Anwendung des Modells nicht erforderlich ist.

Sergey optimierte die Größe des Datensatzes, um ihn auf der GPU auszuführen. Die einfachste Möglichkeit besteht darin, einen Teil der Daten abzuschneiden, dies kann jedoch auf verschiedene Arten erfolgen:

  • Entfernen Sie nach und nach die ältesten Daten (Anfang Februar), bis der Datensatz in den Speicher passt.
  • Merkmale mit der geringsten Wichtigkeit entfernen;
  • Benutzer-IDs entfernen, für die es nur einen Eintrag gibt;
  • Belassen Sie nur die Benutzer-IDs, die im Test enthalten sind.

Und schließlich aus allen Möglichkeiten ein Ensemble machen.

Das letzte Ensemble

Am späten Abend des letzten Tages hatten wir ein Ensemble unserer Modelle erstellt, das einen Wert von 0,742 ergab. Über Nacht habe ich mein Modell mit ctr_complexity=2 gestartet und statt 30 Minuten hat es 5 Stunden lang trainiert. Erst um 4 Uhr morgens wurde gezählt und ich machte das letzte Ensemble, das 0,7433 auf der öffentlichen Bestenliste ergab.

Aufgrund der unterschiedlichen Lösungsansätze des Problems waren unsere Vorhersagen nicht stark korreliert, was zu einer guten Steigerung des Ensembles führte. Um ein gutes Ensemble zu erhalten, ist es besser, die Rohmodellvorhersagen Predict(prediction_type='RawFormulaVal') zu verwenden und Scale_pos_weight=neg_count/pos_count festzulegen.

SNA Hackathon 2019

Auf der Website können Sie sehen endgültige Ergebnisse auf der privaten Bestenliste.

Andere Lösungen

Viele Teams folgten den Regeln der Empfehlungssystemalgorithmen. Da ich kein Experte auf diesem Gebiet bin, kann ich sie nicht bewerten, aber ich erinnere mich an zwei interessante Lösungen.

  • Die Lösung von Nikolay Anokhin. Nikolay, ein Mitarbeiter von Mail.ru, bewarb sich nicht um Preise, daher bestand sein Ziel nicht darin, maximale Geschwindigkeit zu erreichen, sondern eine leicht skalierbare Lösung zu erhalten.
  • Die Entscheidung des preisgekrönten Teams der Jury basiert auf dieser Artikel von Facebook, ermöglichte ein sehr gutes Bild-Clustering ohne manuelle Arbeit.

Abschluss

Was mir am meisten in Erinnerung geblieben ist:

  • Wenn die Daten kategoriale Merkmale enthalten und Sie wissen, wie man die Zielcodierung richtig durchführt, ist es immer noch besser, Catboost auszuprobieren.
  • Wenn Sie an einem Wettbewerb teilnehmen, sollten Sie keine Zeit damit verschwenden, andere Parameter als „learning_rate“ und „Iterationen“ auszuwählen. Eine schnellere Lösung besteht darin, ein Ensemble aus mehreren Modellen zu erstellen.
  • Boostings können auf der GPU erlernt werden. Catboost kann sehr schnell auf der GPU lernen, verbraucht aber viel Speicher.
  • Während der Entwicklung und des Testens von Ideen ist es besser, einen kleinen rsm~=0.2 (nur CPU) und ctr_complexity=1 festzulegen.
  • Im Gegensatz zu anderen Teams hat das Ensemble unserer Modelle einen großen Zuwachs erzielt. Wir haben nur Ideen ausgetauscht und in verschiedenen Sprachen geschrieben. Wir hatten bei der Aufteilung der Daten einen anderen Ansatz und ich glaube, jeder hatte seine eigenen Fehler.
  • Es ist nicht klar, warum die Ranking-Optimierung schlechter abschneidet als die Klassifizierungsoptimierung.
  • Ich habe einige Erfahrungen im Umgang mit Texten gesammelt und ein Verständnis dafür gewonnen, wie Empfehlungssysteme aufgebaut sind.

SNA Hackathon 2019

Vielen Dank an die Organisatoren für die Emotionen, das Wissen und die erhaltenen Preise.

Source: habr.com

Kommentar hinzufügen