Der ivi-Online-Filmblog enthält zahlreiche Artikel zur Architektur des Hydra-Empfehlungssystems. Empfehlungen sind jedoch nicht nur eine externe API, sondern auch Algorithmen, die "unter der Haube" leben und recht komplexe Geschäftslogik implementieren.
In diesem Artikel werde ich über das Problem des "Kaltstarts" von Inhalten sprechen. Wenn Sie erfahren möchten, wie wir kürzlich zum Katalog hinzugefügte Inhalte empfehlen und keine Rückmeldungen von Benutzern erhalten, heißen wir Sie bei cat willkommen.
Der Artikel enthält ein reproduzierbares Beispiel für Python-Code mit Keras.
Inhalt Kaltstart: Problemstellung
Wie funktionieren Empfehlungen? Ungefähr wie folgt:
Wir verwenden die folgende Pipeline für Empfehlungen:
- Laden Sie Statistiken zur Inhaltsansicht in Form einer Matrix mit Benutzerinhalten
- Wenden Sie die Magic Box für maschinelles Lernen an
- am Ausgang der Box erscheinen für jede Einheit die Katalogmerkmale
- wir verwenden inhaltsmerkmale für empfehlungen
Alle Phasen der Trainings-Pipeline für Kaltstartmodelle finden Sie in diesem Repository unter
github.com/ivi-ru/hydraWir erhalten Inhaltsfunktionen mit der impliziten Bibliothek wie folgt
train_model.pyimport implicit import numpy as np from scipy.sparse import load_npz
Wie kann ich Inhalte empfehlen, die kürzlich über den Dienst veröffentlicht wurden? Solche Inhalte haben keine Aufrufe (oder es gibt nur sehr wenige Aufrufe) - dies bedeutet, dass es keine Funktionen für solche Inhalte in der magischen Kiste des maschinellen Lernens gibt und sie nicht in Benutzerempfehlungen enthalten sind. Funktionen, die wir auf der Basis von Benutzer-Content-Interaktionen erhalten, werden als kollaborativ bezeichnet.
So kommen wir zum Problem eines Kaltstarts: Wie können wir Inhalte empfehlen, die kein Benutzer-Feedback haben? Es ist zum Beispiel möglich, neuen Inhalt in eine zufällige Ausgabe zu mischen und zu warten, bis „organische“ Ansichten gesammelt wurden.
Eine weitere Option ist die Erstellung eines Modells, mit dem Merkmale von "kaltem" Inhalt vorhergesagt werden können.
Wir haben uns für den zweiten Weg entschieden und dorthin sind wir gekommen
Kaltstart 1.0
Um das Problem eines Kaltstarts zu lösen, helfen uns Inhaltsfunktionen, die beispielsweise über neue Inhalte im Voraus bekannt sind
- Personen: Regisseur, Drehbuchautor, Darsteller
- Inhaltsgenre: Action, Comedy, etc.
- Kategorie: Spielfilm, Zeichentrickfilm, Dokumentarfilm
- Editor-Tags
Editorial-Tags sind eine kurze Beschreibung des Inhalts in Form einer endlichen (normalerweise mehreren hundert) Menge von Merkmalen. Unten finden Sie eine Reihe von Beaver Zombie-Inhalts-Tags
In erster Näherung haben wir das Kaltstartproblem wie folgt gelöst:
- Wischen Sie für jeden "kalten" Inhalt so ähnlich wie möglich mit Tags
- Nehmen Sie kollaborative Funktionen mit ähnlichen Inhalten
- kollaborative Merkmale von kaltem Inhalt sind der Durchschnitt der Merkmale seiner "heißen" Nachbarn
In Python sieht es ungefähr so aus for row in new_items_neighbors: neighbors_als_indices = row.neighbors_ids[:self.cold_start_neighbors_count] neighbors_average_factors = item_factors[neighbors_als_indices].mean(axis=0)
Diese Methode
funktionierte irgendwie , hatte aber zwei Nachteile:
- Geringe Erweiterbarkeit: Es ist schwierig, beispielsweise die Ähnlichkeit von Postern hinzuzufügen
- Niemand garantiert die Ähnlichkeit von ALS-Funktionen mit Inhalten, die in Tags ähnlich sind, und ohne dies sieht die Verwendung der Mittelung seltsam aus
Wir haben festgestellt, dass Sie so nicht mehr leben können, und sind auf ein transparenteres und erweiterbares Modell gekommen.
Refactoring eines Kaltstartmodells
Anstatt ALS-Inhaltsmerkmale mithilfe von Heuristiken (z. B. Mittelwertbildung) zu berechnen, können wir ein neuronales Netzwerk trainieren, das kollaborative Inhaltsmerkmale vorhersagt - z. B. anhand von Editor-Tags. Ein ähnliches Modell war bereits
bei Habr zu sehen , und vor Yandex
sprach der
Spotify-Musikdienst über ein ähnliches Modell
Der Modellprototypcode ist
im ivi-Repository verfügbar. Das neuronale Netzwerk für einen Kaltstart lautet wie folgt:
cold_start_model.py def _get_model(self, dims: List[int]) -> Sequential: model = Sequential() model.add( Dense( units=dims[1], activation='linear', input_dim=dims[0], kernel_initializer=WeightInitializer.custom_normal, bias_initializer='zeros' ) ) model.compile( loss=lambda y_true, y_pred: K.sum(K.square(y_pred - y_true), axis=-1), optimizer=optimizers.Adam(lr=self.learning_rate, decay=self.decay) ) return model
Auf welche Schwierigkeiten sind Sie bei der Durchführung dieses Experiments gestoßen?
- Es stellte sich als ziemlich schwierig heraus, das Netzwerk zu trainieren: Features werden One-Hot-codiert, und das Netzwerk ist aufgrund der großen Dimension der Eingabeebene schlecht trainiert. Ich musste eine sorgfältige Auswahl der Features vornehmen, am Ende verwenden wir nur Kategorien, Genres und wählen mit tf-idf aus den Editor-Tags die "wichtigsten" aus
- Das Problem bei der Installation von Keras mit dem Pipenv-Paket-Manager: Python, die Umgebung war nicht in Ordnung. Ich musste das Maxvolpy- Paket eines Drittanbieters fertigstellen , mit dem Keras sich nicht angefreundet hatte
Versuchsergebnisse
Infolgedessen haben wir die neue Funktionalität ein wenig reduziert, was der Entwickler für ein paar Sprints etwa 100 Stunden in Anspruch nahm - und dies ist die erste Erfahrung mit dem Einsatz neuronaler Netze in der Produktion in unserem Projekt. Diese Zeit wurde wie folgt verteilt:
- 60 Std. Zum Lesen von Artikeln und zur Entwicklung von Prototypen
- 30 Stunden, um den Prototyp in die Projektcode-Basis zu integrieren
- 10 Stunden für die Bereitstellung des neuen Modells - das Ziehen von Keras in einer Python-Umgebung war aufgrund unserer spezifischen Abhängigkeiten (wie maxvolpy) nicht so einfach
Wir haben Platz für weitere Experimente - die Verwendung neuronaler Netze ermöglicht es Ihnen, nicht nur über Editor-Tags, sondern auch über andere Funktionen zu lernen: Bilder, Skripte, Benutzerkommentare, Filmmaterial usw.